Skip to content

Instantly share code, notes, and snippets.

@fversnel
Created December 30, 2014 11:36
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save fversnel/4aed612b69d3ec196157 to your computer and use it in GitHub Desktop.
Save fversnel/4aed612b69d3ec196157 to your computer and use it in GitHub Desktop.
React SmartSortable
var cloneWithProps = React.addons.cloneWithProps;
var SmartSortable = React.createClass({
getDefaultProps: function() {
return {component: "ul", childComponent: "li"};
},
render: function() {
var props = jQuery.extend({}, this.props);
delete props.children;
return React.createElement(this.props.component, props);
},
componentDidMount: function() {
jQuery(this.getDOMNode()).sortable({stop: this.handleDrop});
this.getChildren().forEach(function(child, i) {
jQuery(this.getDOMNode()).append('<' + this.props.childComponent + ' />');
var node = jQuery(this.getDOMNode()).children().last()[0];
node.dataset.reactSortablePos = i;
React.render(cloneWithProps(child), node);
}.bind(this));
},
componentDidUpdate: function() {
var childIndex = 0;
var nodeIndex = 0;
var children = this.getChildren();
var nodes = jQuery(this.getDOMNode()).children();
var numChildren = children.length;
var numNodes = nodes.length;
while (childIndex < numChildren) {
if (nodeIndex >= numNodes) {
jQuery(this.getDOMNode()).append('<' + this.props.childComponent + '/>');
nodes.push(jQuery(this.getDOMNode()).children().last()[0]);
nodes[numNodes].dataset.reactSortablePos = numNodes;
numNodes++;
}
React.render(cloneWithProps(children[childIndex]), nodes[nodeIndex]);
childIndex++;
nodeIndex++;
}
while (nodeIndex < numNodes) {
React.unmountComponentAtNode(nodes[nodeIndex]);
jQuery(nodes[nodeIndex]).remove();
nodeIndex++;
}
},
componentWillUnmount: function() {
jQuery(this.getDOMNode()).children().get().forEach(function(node) {
React.unmountComponentAtNode(node);
});
},
getChildren: function() {
// TODO: use mapChildren()
return this.props.children || [];
},
handleDrop: function() {
var newOrder = jQuery(this.getDOMNode()).children().get().map(function(child, i) {
var rv = child.dataset.reactSortablePos;
child.dataset.reactSortablePos = i;
return rv;
});
this.props.onSort(newOrder);
}
});
@shilu89757
Copy link

Why use the function 0f jQuery.extend() ?
var props = jQuery.extend({}, this.props);
delete props.children;

@garmjs
Copy link

garmjs commented Nov 15, 2015

@shilu89757 $.extend merge the contents of two or more objects together into the first object, in this case he is creating a default object and overwriting with whatever come in from this.props.

@fabpico
Copy link

fabpico commented Feb 27, 2018

@fversnel Do you also have a solution for connected sortables? Drag and drop from a list to another.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment