Вопрос по javascript – Сохранение заказа jQuery UI Sortable в коллекцию Backbone.js

45

У меня есть коллекция Backbone.js, которую я хотел бы иметь возможность сортировать с помощью сортируемого пользовательского интерфейса jQuery. Ничего особенного, у меня просто есть список, который я бы хотел отсортировать.

Проблема заключается в том, что я не уверен, как получить текущий порядок элементов после сортировки и передать его в коллекцию. Сортируемый может сериализоваться сам, но это не даст мне данные модели, которые я должен предоставить в коллекцию.

В идеале я хотел бы иметь возможность просто получить массив текущего порядка моделей в коллекции и использовать метод сброса для коллекции, но я не уверен, как получить текущий заказ. Пожалуйста, поделитесь идеями или примерами получения массива с текущим порядком моделей.

Ваш Ответ

3   ответа
6

Backbone.CollectionView!

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

Вуаля!

Error: User Rate Limit Exceeded
9

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).
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;
}
Error: User Rate Limit Exceeded$elError: User Rate Limit Exceeded
Error: User Rate Limit ExceededlistupdateError: User Rate Limit ExceededupdateError: User Rate Limit Exceeded
Error: User Rate Limit Exceededthis.$el.children().remove();Error: User Rate Limit Exceeded_.invoke(this.viewItems, 'remove')Error: User Rate Limit Exceeded
81

чтобы вызвать событие в представлении элемента, когда элемент отброшен. Затем я могу вызвать другое событие в представлении элемента, которое включает модель в качестве данных, с которыми связано представление коллекции. В этом случае представление коллекции может отвечать за обновление порядка сортировки.

Working example

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

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());
        }
    });
});

стоп событие связано с функцией, которая вызываетdrop на узле DOM для элемента с индексом элемента (предоставленным пользовательским интерфейсом jQuery) в качестве данных.

Item view
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;
    }
});

Событие отбрасывания связано сdrop функция, которая вызываетupdate-sort событие в узле DOM представления элемента с данными[this.model, index], Это означает, что мы передаем текущую модель и ее индекс (из сортируемого пользовательского интерфейса jQuery) тому, кто связан сupdate-sort событие.

Items (collection) view
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();
    }
}); 

Items вид связан сupdate-sort событие и функция использует данные, переданные событием (модель и индекс). Модель удалена из коллекции,ordinal Атрибут обновляется для каждого оставшегося элемента, и порядок элементов по идентификатору отправляется на сервер для сохранения состояния.

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

Коллекция имееткомпаратор определена функция, которая упорядочивает коллекцию поordinal, Это сохраняет синхронизированный порядок отображаемых элементов как «порядок по умолчанию». коллекции теперь по значениюordinal приписывать.

Заметьте, что имеется некоторое дублирование усилий: модель не нужно удалять и добавлять обратно в коллекцию, если коллекция имеет функцию сравнения, как jsfiddle. Также представление может не нуждаться в повторной визуализации.

NoteПо сравнению с другим ответом, я чувствовал, что правильнее было бы уведомить экземпляр модели элемента о том, что его нужно обновить, а не напрямую из коллекции. Оба подхода действительны. Другой ответ здесь идет непосредственно в коллекцию вместо того, чтобы использовать подход сначала модель. Выберите тот, который имеет больше смысла для вас.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededThis event is triggered when the user stopped sorting and the DOM position has changed.Error: User Rate Limit Exceeded

Похожие вопросы