How would you make this?
The items in the list could correspond to records in a collection, and their position in the list could correspond to a field on each record ("rank" perhaps) which would have to be updated when the 'stop' event occurred.
Would Meteor play nicely with jQueryUI Sortable? What would happen if multiple users attempted to drag and sort the same list at once? Would Meteor need a customized sorting behavior?
**Updated for 1.0
Check out MeteorPad: http://meteorpad.com/pad/TzQTngcy7PivnCCjk/sortable%20demo
Here is the version I implemented - very similar to @tomsabin's, but no Collection Behaviors needed. It has worked well for me with multiple users and is reactive.
HTML (Probably not a good idea to make the div id the same as _id, I'm sure you'll find a better workaround.)
<template name="myList">
<div class="step_list">
{{#each card}}
{{> card_template}}
{{/each}}
</div>
</template>
<template name="card_template">
<div class="card" id="{{_id}}">
<h3>{{name}}</h3>
</div>
</template>
JS
Template.myList.helpers ({
card : function () {
return Cards.find({}, {sort: {pos: 1}}
)}
})
Template.myList.rendered = function(){
$(".step_list").sortable({
items: ".card",
delay: 100,
refreshPositions: true,
revert: true,
helper: "clone",
scroll: true,
scrollSensitivity: 50,
scrollSpeed: 35,
start: function(event, ui) {
$(ui.helper).addClass("dragging");
}, // end of start
stop: function(event, ui) {
$(ui.item).removeClass("dragging");
}, // end of stop
update: function(event, ui) {
var index = 0;
_.each($(".card"), function(item) {
Cards.update({_id: item.id}, {
$set:{
pos: index++,
}
});
});
}
}).disableSelection();
}
Meteor's new rendering engine Blaze now plays with jQuery much more nicely. Here is short video which shows how to implement a sortable list with Meteor and jQuery-UI-sortable.
The code can be found in the Meteor repository on GitHub in the example folder.
EDIT: The below answer is out of date, @cutemachine's answer or http://blog.differential.com/sortable-lists-in-meteor-using-jquery-ui is much closer to the state of the art.
The short answer is: this isn't easy if you want it to be reactive. To make a non-reactive version, just wrap your template in a {{#constant}}
tag and hook up the jquery-ui sortable in render
as @bento suggested.
To make a reactive version, your sortable widget is going to have to deal with things changing under it (think about being mid-drag when data re-orders itself). Here are some thoughts about how you would go about it:
Unfortunately, it's not going be easy to make it animate, which is going to lead to poor UX. Let's leave that aside for now.
Render the items with something like:
{{#each items}}
{{> item}}
{{/item}}
This will re-order itself when data comes down from the server (without animation).
Set up each item to be draggable when it renders. You could either
i. Use something like jquery-ui draggable, and hook it up in render
on the item
template. You might have problems doing this as the underlying element may disappear during a drag if the ordering changes from upstream.
ii. implement your own dragging code, perhaps using a lower level library.
When an item is dragged into position, immediately reorder the list locally (that way the user should see the right thing. Hopefully the server will respect the change.. but let's not get into that either).
I think there is a big need for such a widget, done in a meteoric way. It's on my personal radar (but so are a lot of things, including a nice way to re-order with animation).
The most recent example of sortable lists with Meteor and jQuery UI was posted in October 2014 by Differential:
http://differential.com/blog/sortable-lists-in-meteor-using-jquery-ui
Note that previous solutions may not work after Meteor switched to the Blaze templating engine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With