React-js-todo-list-sortable(5)

Building a Todo app with React.js (5) - sort item

TodoListApp

The next step is to allows users to change the sequence of ToDoListItem using drag and drop (DnD)

We will allow user to sort an array using drag and drop. We create li element first.

var placeholder = document.createElement("li");
    placeholder.className = "placeholder";

Component 1 - ToDoList

We create the DragStar function, DragEnd function and DragOver function to implement (Drag and drop)DnD process.

DragStart: function(e){
    this.dragged = e.currentTarget;
    e.dataTransfer.effectAllowed = 'move';
},
DragEnd: function(e){
    this.dragged.style.display="";
    var IshasNode = false

    Array.prototype.forEach.call (this.dragged.parentNode.childNodes, function (node) {
        if(node.className=="placeholder")
                        IshasNode = true;

    } );
    if(!IshasNode)
    return;
    this.dragged.parentNode.removeChild(placeholder);
    var data = this.props.items;
    var from = Number(this.dragged.dataset.id);
    var to = Number(this.over.dataset.id);
    if(from < to) to--;
    if(this.nodePlacement == "after") to++;
    data.splice(to, 0, data.splice(from, 1)[0]);
    this.setState({data: data});    
},
DragOver: function(e) {

    e.preventDefault();
    this.dragged.style.display = "none";

    if(e.target.className == "placeholder") return;
    this.over = e.target;
    // Inside the dragOver method
    var relY = e.clientY - this.over.offsetTop;
    var height = this.over.offsetHeight / 2;
    var parent = e.target.parentNode;

    if(relY > height) {
      this.nodePlacement = "after";
      parent.insertBefore(placeholder, e.target.nextElementSibling);
    }
    else if(relY < height) {
      this.nodePlacement = "before"
      parent.insertBefore(placeholder, e.target);
    }
},

DragStar function and DragEnd function are bound to ToDoListItem component.

    var createItem = function(itemText,i) {
        return (
            <ToDoListItem key={i} value={i} onDragEnd={this.DragEnd}
onDragStart={this.DragStart} onRemove = {this.Remove}>{itemText}</ToDoListItem>
        );
    };

DragOver function are bound to ul element.

<ul onDragOver={this.DragOver}>{allitems.map(createItem,this)}</ul>;

Component 2 - ToDoListItem

We create DragEndHandler function and DragStartHandler function to trigger parent’s event and also bind to li element. We also need to set the draggable = true attribute on the li element.

DragEndHandler : function(e){
    this.props.onDragEnd(e);
},
DragStartHandler : function(e){
    this.props.onDragStart(e);
},
render: function(){
    var _style = "line-through";
    if(!this.props.children.isDone)
    _style ="none";
    return (
      <li data-id={this.props.value} 
                key={this.props.value} draggable="true" onDragEnd={this.DragEndHandler}
            onDragStart={this.DragStartHandler}><button type="button" className="close pull-right" aria-hidden="true" onClick={this.RemoveHandler}>&times;</button><input type="checkbox" onChange={this.ChangeHandler} defaultChecked={this.props.children.isDone} /><span style={{"textDecoration": _style}}>{this.props.children.item}</span></li>
    );
}

When you finish , you can see the TodoApp.
TodoListApp
The complete working demo can be found here .

##Building a Todo app with React.js (1) - A simple todos list

##Building a Todo app with React.js (2) - Improve Component & Remove Component

##Building a Todo app with React.js (3) - Adding Filters for Search and showing complete/incompleted tasks

##Building a Todo app with React.js (4) - Multiple Todos

##Building a Todo app with React.js (5) - Sort item