Jquery Draggable и Backbone.js получают ссылку на модель магистрали из обратного обратного вызова. - PullRequest
27 голосов
/ 07 сентября 2011

У меня есть модель скелета, которую я рендерирую здесь, и делаю ее перетаскиваемой с помощью jquery ui.

render: ->
$(this.el).attr('class', 'item').html(this.template(this.options.model.toJSON() ))
viewmodel = this
$(this.el).draggable
    revert: true
    drag: () ->
        console.log(viewmodel)

Выше у меня есть доступная модель представления, и я могу удалить ее из dom, вызывать методы для ее модели и т. Д. Но я хочу перетащить эту модель представления в выпадающий контейнер - как корзинуможет-- а затем вызвать несколько методов модели представления и удалить его из DOM.

Я вижу, однако, что метод обратного вызова, когда элемент помещается в контейнер, будет:

$(function() {
    $("#trash").droppable({
        drop: function(event, ui) {
          console.log(ui.draggable);
        }
    });
});

Итак, я могу увидеть ui.draggable и удалить егоиз DOM, но я не имею никакого отношения к его модели представления.Я делаю что-то неправильно?Есть ли способ обойти это?

Ответы [ 4 ]

41 голосов
/ 12 октября 2011

Я думаю, что столкнулся с той же проблемой;вместо того, чтобы добавлять метаданные к элементу или хранить его глобально, я просто сохранил ссылку на фактическое представление самого элемента DOM, который затем дает вам доступ к модели и любой необходимой информации оттуда.

window.MyDraggableView = Backbone.View.extend({
    initialize: function(){
        $(this.el).draggable();
        $(this.el).data("backbone-view", this);
    }
});

window.MyDropTarget = Backbone.View.extend({
    initialize: function(){
        $(this.el).droppable({
            drop: function(ev, ui){
                // get reference to dropped view's model
                var model = $(ui.draggable).data("backbone-view").model;
            },
        });
    },
});
18 голосов
/ 07 сентября 2011

У меня была эта проблема.Я решил это так: дайте цели сброса ссылку на коллекцию моделей.Установите свойство data-cid="<%= cid %>" для перетаскиваемого объекта.Теперь вы можете посмотреть модель в коллекции из $(ui.draggable).data('cid').Поскольку магистраль утверждает, что идентификаторы CID уникальны, вы даже можете сканировать коллекцию коллекций, если существует несколько классов моделей, которые вы хотите перевести.

11 голосов
/ 11 мая 2012

Подход, который я использую, заключается в передаче события от перетаскиваемого объекта к перетаскиваемому через пользовательское событие.

var DroppableView = Backbone.View.extend({
  events: { 'drop': 'dropHandler' },
  initialize: function() { this.$el.droppable(); },
  dropHandler: function(e, ui) { ui.draggable.trigger('drop:dropview'); }
})

var DraggableView = Backbone.View.extend({
  events: { 'drop:dropview': 'dropviewDropHandler'},
  initialize: function(){ this.$el.draggable(); },
  dropviewDropHandler: function() { this.doSomething(); }
});

Это позволяет вам запускать обработчик отбрасывания в контексте перетаскиваемого представления, которое частоболее полезно, чем его выполнение в контексте отбрасываемого представления.

1 голос
/ 20 сентября 2011

Мы решили эту проблему с помощью глобального свойства, которое помещается в пространство имен приложения и называется перетаскиванием.

Поскольку перетаскивается только один вид, вид перетаскивания привязывается к событию перетаскивания и записывает свою собственную модель в window.dragging.

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

кстати, это свойство лучше разместить в глобальном доступном пространстве имен приложения, а не добавлять его непосредственно в окно. Это был App.View.tool в нашем приложении.

Как это:

dragging = null;

draggableview = new Backbone.View.extend({

    //...
    initialize: function() {

        //...
        $(this.el).bind("dragStart",
        function() {
            window.dragging = this.model;
        },
        this);

        //remove reference for garbage collection purpose
        $(this.el).bind("dragStop",
        function() {
            delete window.dragging;
        },
        this);
    },

});

droppableview = new Backbone.View.extend({

    //...
    initialize: function() {

        //...
        $(this.el).bind("drop",
        function() {
            var draggedmodel = window.dragging;
            delete window.dragging;
            // for garbage collection purpose
            //do funky stuff
            alert("You dropped " + draggedmodel.get('title') + " on " + this.el.get('title'));
            //...
        },
        this);
    },
});
...