3

I need to render the content from this div:

  <div class="col-sm-4">
                  <ul class="list-group">
                  <li class="list-group-item"><a href="#">File Reader</a></li>
                  <li class="list-group-item" ><a href="#">File Move</a></li>
                  <li class="list-group-item" ><a href="#">Data Base</a></li>
                  <li class="list-group-item"><a href="#">SAP R3</a></li>
                  <li class="list-group-item"><a href="#">FTP</a></li>
                  <li class="list-group-item"><a href="#">SOAP</a></li>
                  <li class="list-group-item"><a href="#">Rest</a></li>
                  <li class="list-group-item"><a href="#">Merge</a></li>
                  <li class="list-group-item"><a href="#">Filter</a></li>
                  <li class="list-group-item"><a href="#">Transform</a></li>
              </ul>
              </div>

Into a Drag and Drop, i tried a lot of examples but nothing seems to work.

Here is my code right now :

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { DragSource } from 'react-dnd';
import { ItemTypes } from './Constants';
import styles2 from './Styles.css'
import { render } from 'react-dom';
import {DragDropContext} from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';

const styles = {
  fontFamily: 'sans-serif',
  textAlign: 'center', 
};



function collect(connect, monitor) {
  return {
    connectDragSource: connect.dragSource(),
    isDragging: monitor.isDragging()
  };
}
function _(id){
   return document.getElementById(id);  
}
var droppedIn = false;
function drag_start(event) {
    _('app_status').innerHTML = "Dragging the "+event.target.getAttribute('id');
    event.dataTransfer.dropEffect = "move";
    event.dataTransfer.setData("text", event.target.getAttribute('id') );
}
function drag_enter(event) {
    _('app_status').innerHTML = "You are dragging over the "+event.target.getAttribute('id');
}
function drag_leave(event) {
    _('app_status').innerHTML = "You left the "+event.target.getAttribute('id');
}
function drag_drop(event) {
    event.preventDefault(); /* Prevent undesirable default behavior while dropping */
    var elem_id = event.dataTransfer.getData("text");
    event.target.appendChild( _(elem_id) );
    _('app_status').innerHTML = "Dropped "+elem_id+" into the "+event.target.getAttribute('id');
    _(elem_id).removeAttribute("draggable");
    _(elem_id).style.cursor = "default";
    droppedIn = true;
}
function drag_end(event) {
    if(droppedIn == false){
        _('app_status').innerHTML = "You let the "+event.target.getAttribute('id')+" go.";
    }
  droppedIn = false;
}
function readDropZone(){
    for(var i=0; i < _("drop_zone").children.length; i++){
        alert(_("drop_zone").children[i].id+" is in the drop zone");
    }
    /* Run Ajax request to pass any data to your server */
}
const propTypes = {
  text: PropTypes.string.isRequired,

  // Injected by React DnD:
  isDragging: PropTypes.bool.isRequired,
  connectDragSource: PropTypes.func.isRequired
};

class BasicForm extends React.Component {

  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }



   render() {
    return (

      <div style={styles}>
       <form onSubmit={this.handleSubmit}>


        <div class="container">
            <div class="row">
             <div class="col-sm-4">
                      <ul class="list-group">
                      <li class="list-group-item"><a href="#">File Reader</a></li>
                      <li class="list-group-item" ><a href="#">File Move</a></li>
                      <li class="list-group-item" ><a href="#">Data Base</a></li>
                      <li class="list-group-item"><a href="#">SAP R3</a></li>
                      <li class="list-group-item"><a href="#">FTP</a></li>
                      <li class="list-group-item"><a href="#">SOAP</a></li>
                      <li class="list-group-item"><a href="#">Rest</a></li>
                      <li class="list-group-item"><a href="#">Merge</a></li>
                      <li class="list-group-item"><a href="#">Filter</a></li>
                      <li class="list-group-item"><a href="#">Transform</a></li>
                  </ul>
                  </div>
              <h2 id="app_status">App status...</h2>
              <h1>Drop Zone</h1>
              <div id="drop_zone"  onDragEnter="drag_enter(event)" onDrop="drag_drop(event)" onDragOver="return false" onDragLeave="drag_leave(event)" className={styles2.drop_zone} ></div>

              </div>
          </div>
          <input type="submit" value="Submit" />
      </form>  
       </div>
    );
  }

}export default DragDropContext(HTML5Backend)(BasicForm);

On my console i get this error : Expected onDragEnter listener to be a function, instead got a value of string type. What i'm doing wrong? PS: I'm new with React, i tried so many examples, so the code is a little bit big.

8
  • 1) react-sortable-hoc 2) react-beautiful-dnd 3) react-dnd Commented Jan 24, 2018 at 1:24
  • 1
    Already tried the 3, none worked, i want to know how to do it, i know the libs already, in this case i'm using react-dnd Commented Jan 24, 2018 at 10:07
  • Hi! In this particular example the error is that you are providing (just as it says) strings instead of functions as event handlers. To fix this error you need to change onDrag...="..." into onDrag..={() => ...} I am afraid it won't really help because, I've just checked the code, it's done in a none react way completely. In react you don't fiddle with dom objects manually, also you drag items/drag containers should we properly wrapped with react-dnd functions, etc.. Probably you could check the tutorial and copy the logic from there. Commented Jan 24, 2018 at 15:22
  • Frankly speaking react-dnd is more complicated to with as it requires more manual setup and doesn't provide animations out of the box, which you probably would like to have Commented Jan 24, 2018 at 15:23
  • I'm trying to make without a lib, but i cant pass the OnDragOver = false, do u know how to do it? Commented Jan 24, 2018 at 17:33

2 Answers 2

4

This is a basic drag and drop example for list in react. Does not handle the dropping yet, only the dragging and the scroll.

const getWindowScroll = () => {
    const doc = document.documentElement;
    return (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
  }

class App extends React.Component {
  setElemRef = ref => {
    this.elemRef = ref;
  }
  
  initialiseDrag = event => {
    const {target, clientY} = event;
    const { offsetTop } = target;
    const { top } = this.elemRef.getBoundingClientRect();
    this.dragStartTop = top - offsetTop;
    this.dragStartY = clientY;
    window.addEventListener('mousemove', this.startDragging, false);
    window.addEventListener('mouseup', this.stopDragging, false);
  }
  
  startDragging = ({ clientY }) => { 
    let newTop = this.dragStartTop + clientY - this.dragStartY + getWindowScroll();
    if (newTop < 0) newTop = 0;
    this.elemRef.style.transform = `translateY(${newTop}px)`;
    this.scrollIfElementBottom(newTop);
  }

  stopDragging = () => {
    window.removeEventListener('mousemove', this.startDragging, false);
    window.removeEventListener('mouseup', this.stopDragging, false);
  }  
  
  scrollIfElementBottom = newTop => {
    if (newTop > 30) {
      window.scroll({
        top: newTop,
        behavior: 'smooth'
      });    
    }
    if (newTop < 30) {
      window.scroll({
        top: 0,
        behavior: 'smooth'
      });      
    }
  };
  
  render(){
    return (
      <React.Fragment>
        <div onMouseDown={this.initialiseDrag} ref={this.setElemRef}>DragMe</div>
        <div>List elem</div>
        <div>List elem</div>
        <div>List elem</div>
        <div>List elem</div>
        <div>List elem</div>
        <div>List elem</div>
        <div>List elem</div>
        <div>List elem</div>
      </React.Fragment>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
#root div {
  background: gray;
  padding: 20px;
  margin: 10px;
  user-select: none;
  cursor: pointer;
  border: 1px solid lightgray;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Sign up to request clarification or add additional context in comments.

Comments

1

https://github.com/peterh32/react-drag-drop-container is a pretty simple library. If I understand what you are trying to do (drag LIs into the "Drop Zone"), you'd do something like this for each LI:

<DragDropContainer onDrop={...} onDragStart={...} ...etc. >
  <li class="list-group-item"><a href="#">File Reader</a></li>
</DragDropContainer>

...and then for your drop zone:

<DropTarget onHit={...} onDragEnter={...} ...etc.>
  <div id="drop-target">...</div>
</DropTarget>

The events go right into the containers as you can see. It handles mouse and touch interfaces and also does stuff like scrolling when you get to the edge of the screen (so you can drag to destinations that are initially offscreen).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.