Jquery Draggable и Backbone.js получают ссылку на базовую модель изнутри обратного вызова с возможностью отказа
У меня есть модель базового вида, которую я просматриваю здесь, и перетаскивая ее с помощью 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)
Выше, у меня есть viewmodel и вы можете удалить его из dom, вызвать методы на своей модели и т.д. Но я хочу перетащить эту модель представления в контейнер с возможностью удаления - например, с помощью мусора, а затем вызвать некоторые из методов модели представления и удалите их из DOM.
Что я вижу, это метод обратного вызова, когда элемент упал в контейнер:
$(function() {
$("#trash").droppable({
drop: function(event, ui) {
console.log(ui.draggable);
}
});
});
Итак, я могу видеть ui.draggable и удалить его из DOM, но у меня нет ссылки на его модель представления. Я делаю что-то неправильно? Любой способ обойти это?
Ответы
Ответ 1
У меня была эта проблема. Я решил это так: Дайте целевой цели ссылку на коллекцию моделей. Задайте свойство data-cid="<%= cid %>"
для перетаскиваемого объекта. Теперь вы можете найти модель в коллекции из $(ui.draggable).data('cid')
. Поскольку базовая группа утверждает, что идентификаторы CID уникальны, вы даже можете отсканировать коллекцию коллекций, если есть несколько классов моделей, которые вы хотели бы сбрасывать.
Ответ 2
Я думаю, что столкнулся с той же проблемой; вместо того, чтобы добавлять метаданные к элементу или хранить его во всем мире, я просто сохранил ссылку на фактическое представление непосредственно на элемент 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 model
var model = $(ui.draggable).data("backbone-view").model;
},
});
},
});
Ответ 3
Подход, который я использую, заключается в передаче события из droppable в draggable через настраиваемое событие.
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(); }
});
Это позволит вам выполнить обработчик перетаскивания в контексте перетаскиваемого представления, что часто более полезно, чем выполнение его в контексте раскрывающегося вида.
Ответ 4
Мы решили эту проблему с глобальным свойством, которое помещается в пространство имен приложений, называемое dragging.
Поскольку в одно время перетаскивается только один вид, перетаскивающий вид привязывается к событию перетаскивания и записывает свою собственную модель в window.dragging.
Когда он падает на раскрывающемся представлении, это представление получает текущую модель перетаскивания с помощью этой переменной перетаскивания.
btw это свойство может быть лучше помещено в глобальное доступное пространство имен приложений вместо прямого добавления его в окно. Это наш 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);
},
});