4

I need some guidance/suggestions for an optimal way to save the order of a sortable list that takes advantage of Meteor.

The following is a scaled down version of what I'm trying to do. The application is a simple todo list. The end goal for the user is to sort their list where the data is picked up from the database. As the user sorts tasks, I would like to save the order of the tasks.

I've implemented this application without Meteor using php/ajax calls using sortable's update event that would delete the entry in the database and replace it with what was currently in the DOM. I'm curious to know if there are a better ways to do this taking advantage of Meteor's capabilities.

The following sample code is straight off of a live demo.

HTML:

<template name="todo_list">
    <div class="todo_list sortable">
       {{#each task}}
            <div class="task">
                <h1>{{title}}</h1>  
                {{description}} 
            </div>
        {{/each}}
    </div>
</template>

JS(Without the Meteor.isServer that simply populates the database.):

if (Meteor.isClient) {
     //Populate the template
     Template.todo_list.task = function () {
        return Tasks.find({});
     };

     //Add sortable functionality
     Template.todo_list.rendered = function () {
        $( ".sortable" ).sortable();
        $( ".sortable" ).disableSelection();
     };
}

Sample data (Output of Tasks.find({})):

[{
   title:"CSC209",
   description:"Assignment 3"
 },
 {
   title:"Laundry",
   description:"Whites"
 },
 {
   title:"Clean",
   description:"Bathroom"
 }]
Petahhh
  • 287
  • 3
  • 8

1 Answers1

5

You'd probably want to first sort your items by a new field on you collection then, you'll want to hook into the jQuery sortable update event:

if (Meteor.isClient) {
     // Populate the template
     Template.todo_list.task = function () {
        return Tasks.find({}, { sort: ['order'] });
     };

     // Add sortable functionality
     Template.todo_list.rendered = function () {
        $('.sortable').sortable({
            update: function (event, ui) {
                // save your new list order based on the `data-id`.
                // when you save the items, make sure it updates their
                // order based on their index in the list.
                some_magic_ordering_function()
            }
        });
        $( ".sortable" ).disableSelection();
     };
}

You template would look a bit like this:

<template name="todo_list">
    <div class="todo_list sortable">
       {{#each task}}
            <div class="task" data-id="{{_id}}">
                <h1>{{title}}</h1>  
                {{description}} 
            </div>
        {{/each}}
    </div>
</template>

And when that event is triggered, it would determine the order of the list and save the new order in the documents for the collection.

This isn't really a complete answer, but hopefully it helps a bit.

Dana Woodman
  • 4,148
  • 1
  • 38
  • 35
  • Thank you. This solution will be efficient enough for what I'm working on where the list is relatively short. I was thinking maybe a linked list may be super fast but there is no way to replicate the idea of a pointer without traversing all elements. – Petahhh Dec 19 '12 at 13:30