45 votes

Enregistrement de la commande de jQuery UI Sortable dans la collection Backbone.js

J'ai un Backbone.js collection que j'aimerais être capable de trier à l'aide de jQuery UI Sortable. Rien de compliqué, j'ai une liste que je voudrais être en mesure de trier.

Le problème est que je ne suis pas sûr de la façon de récupérer les éléments dans l'ordre après avoir été triés et le communiquer à la collection. Sortable pouvez sérialiser lui-même, mais qui ne me donne pas le modèle de données dont j'ai besoin pour donner à la collection.

Idéalement, je voudrais être en mesure de simplement obtenir un tableau de l'ordre actuel des modèles dans la collecte et l'utilisation de la méthode de réinitialisation pour la collection, mais je ne suis pas sûr de la façon d'obtenir la commande en cours. Merci de faire part de leurs idées ou des exemples pour obtenir un tableau avec le modèle actuel de l'ordre.

81voto

Cymen Points 4176

J'ai fait cela à l'aide de jQuery UI Sortable pour déclencher un événement sur le point de vue lorsqu'un élément est supprimé. J'ai peut alors déclencher un autre événement sur le point de vue qui inclut le modèle de données dont la collecte de vue est lié. La collecte de vue peut alors être responsable de la mise à jour de l'ordre de tri.

Exemple de travail

http://jsfiddle.net/7X4PX/4/

jQuery UI Sortable

$(document).ready(function() {
    $('#collection-view').sortable({
        // consider using update instead of stop
        stop: function(event, ui) {
            ui.item.trigger('drop', ui.item.index());
        }
    });
});

L' arrêt de l'événement est lié à une fonction qui déclenche drop sur le nœud DOM pour l'élément avec l'élément d'indice (fourni par jQuery UI) en tant que données.

Point de vue

Application.View.Item = Backbone.View.extend({
    tagName: 'li',
    className: 'item-view',
    events: {
        'drop' : 'drop'
    },
    drop: function(event, index) {
        this.$el.trigger('update-sort', [this.model, index]);
    },        
    render: function() {
        $(this.el).html(this.model.get('name') + ' (' + this.model.get('id') + ')');
        return this;
    }
});

La baisse de l'événement est lié à l' drop fonction qui déclenche une update-sort événement sur le point de vue du nœud DOM avec les données de l' [this.model, index]. Cela signifie que nous sommes en train de le modèle actuel et de l'index (à partir de jQuery UI sortable) à quiconque est lié à l' update-sort événement.

Les éléments (collection) vue

Application.View.Items = Backbone.View.extend({
    events: {
        'update-sort': 'updateSort'
    },
    render: function() {
        this.$el.children().remove();
        this.collection.each(this.appendModelView, this);
        return this;
    },    
    appendModelView: function(model) {
        var el = new Application.View.Item({model: model}).render().el;
        this.$el.append(el);
    },
    updateSort: function(event, model, position) {            
        this.collection.remove(model);

        this.collection.each(function (model, index) {
            var ordinal = index;
            if (index >= position) {
                ordinal += 1;
            }
            model.set('ordinal', ordinal);
        });            

        model.set('ordinal', position);
        this.collection.add(model, {at: position});

        // to update ordinals on server:
        var ids = this.collection.pluck('id');
        $('#post-data').html('post ids to server: ' + ids.join(', '));

        this.render();
    }
}); 

L' Items point de vue est lié à l' update-sort événement et la fonction utilise les données transmises par l'événement (modèle et l'index). Le modèle est supprimé de la collection, l' ordinal attribut est mis à jour sur chaque élément et l'ordre des éléments d'identification est envoyée au serveur pour stocker l'état.

Collection

Application.Collection.Items = Backbone.Collection.extend({
    model: Application.Model.Item,
    comparator: function(model) {
        return model.get('ordinal');
    },
});

La collection est un comparateur de fonction définie à l'commandes de la collection en ordinal. Cela permet de maintenir le rendu de l'ordre des éléments dans sync comme "par défaut" de la collection est maintenant par la valeur de l' ordinal d'attribut.

Remarque il existe un certain chevauchement des efforts: le modèle n'a pas besoin d'être retirés et ajoutés à la collection, si une collection est un comparateur de fonction que le jsfiddle n'. Aussi la vue peut-être pas besoin de re-rendre lui-même.

Remarque: par rapport à l'autre réponse, mon sentiment était qu'il était plus correct de le notifier à l'instance du modèle de l'élément qui doit être mis à jour à la place de la collection, directement. Les deux approches sont valables. L'autre réponse ici va directement à la collecte, au lieu de prendre le modèle de la première approche. Choisissez laquelle plus de sens pour vous.

9voto

http://jsfiddle.net/aJjW6/2/

HTML:

 `<div class="test-class">
     <h1>Backbone and jQuery sortable - test</h1>
     <div id="items-collection-warper"></div>
</div>`
 

JavaScript:

 $(document).ready(function(){

var collection = [
    {name: "Item ", order: 0},
    {name: "Item 1", order: 1},
    {name: "Item 2", order: 2},
    {name: "Item 3", order: 3},
    {name: "Item 4", order: 4}
];
var app = {};

app.Item = Backbone.Model.extend({});
app.Items = Backbone.Collection.extend({
    model: app.Item,
    comparator: 'order',

});

app.ItemView = Backbone.View.extend({
    tagName: 'li',
    template: _.template('<span><%= name %> - <b><%= order %></b></span>'),
    initialize: function(){

    },
    render: function(){
        var oneItem = this.$el.html(this.template(this.model.attributes));
        return this;
    }
});

app.AppView = Backbone.View.extend({
    el: "#items-collection-warper",
    tagName: 'ul',
    viewItems: [],
    events:{
        'listupdate': 'listUpdate'
    },
    initialize: function(){
        var that = this;

        this.$el.sortable({
             placeholder: "sortable-placeholder",
            update: function(ev, ui){
               that.listUpdate();
            }
        });            
    },
    render: function(){
        var that= this;
        this.collection.each(function(item){
            that.viewItems.push(that.addOneItem(item));
            return this;
        });

    },
    addOneItem: function(item){
        var itemView = new app.ItemView({model: item});
        this.$el.append(itemView.render().el);

        return itemView;
    },

    listUpdate: function(){


        _.each(this.viewItems, function(item){
            item.model.set('order', item.$el.index());
        });
        this.collection.sort({silent: true})
         _.invoke(this.viewItems, 'remove');
        this.render();
    }
});

var Items = new app.Items(collection)
var appView = new app.AppView({collection: Items});
appView.render();
});
 

CSS:

 .test-class{
    font-family: Arial;
}
.test-class li{
    list-style:none;
    height:20px;

}
.test-class h1{
    font-size: 12px;
}
.ui-sortable-helper{
    opacity:0.4;
}
.sortable-placeholder{
    background: #ddd;
    border:1px dotted #ccc;
}
 

6voto

Brave Dave Points 802

Il suffit d'utiliser Backbone.CollectionView !

 var collectionView = new Backbone.CollectionView( {
  sortable : true,
  collection : new Backbone.Collection
} );
 

Voila!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X