Building a Todo app with React.js (5) - sort item
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}>×</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.
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