我使用jQuery UI可排序Ember,它工作得很好,直到我想在排序后删除一些项目。这个问题已经在stackoverflow上回答了,但这个解决方案不适合我。我用的是Ember 2.6。
组件模板<ui id="department_roles">
{{#each sortedList as |item|}}
{{item.id}}
<li data-id="{{item.id}}" role_id="{{item.id}}" class="ui-state-default role_droppable">
<span>
{{item.name}}
</span>
<button {{action "removeItem" item.id}}>Remove</button>
</li>
{{/each}}
</ui>
组件,排序工作良好,删除操作项后从数组中删除,但DOM是不正确的。
import Ember from 'ember';
export default Ember.Component.extend({
list: Ember.ArrayProxy.create({content: Ember.A()}),
init: function () {
this._super();
this.get('list').pushObject({
id: 1,
index: 1,
name: 'name1'
});
this.get('list').pushObject({
id: 2,
index: 2,
name: 'name2'
});
this.get('list').pushObject({
id: 3,
index: 3,
name: 'name3'
});
this.get('list').pushObject({
id: 4,
index: 4,
name: 'name4'
});
this.get('list').pushObject({
id: 5,
index: 6,
name: 'name5'
});
},
sortProps: ['index:asc'],
sortedList: Ember.computed.sort('list', 'sortProps'),
updateSortedOrder(indices) {
this.beginPropertyChanges();
let tracks = this.get('list').forEach((item) => {
var index = indices[Ember.get(item, 'id')];
if (Ember.get(item, 'index') !== index) {
Ember.set(item, 'index', index);
}
});
this.endPropertyChanges();
},
didRender: function () {
this._super();
var self = this;
Ember.$("#department_roles").sortable({
update: function () {
var indices = {};
Ember.$(this).children().each((index, item) => {
indices[Ember.$(item).data('id')] = index + 1;
});
self.updateSortedOrder(indices);
},
});
Ember.$('#department_roles').disableSelection();
},
actions: {
removeItem: function (itemId) {
var self = this,
deleteItem,
list = this.get('list');
this.$("#department_roles").sortable("destroy");
list.arrayContentWillChange();
list.forEach(function (item) {
if (item.id === itemId) {
deleteItem = item;
}
});
list.removeObject(deleteItem);
list.arrayContentDidChange();
Ember.$("#department_roles").sortable({
update: function () {
var indices2 = {};
Ember.$(this).children().each((index, item) => {
indices2[Ember.$(item).data('id')] = index + 1;
});
self.updateSortedOrder(indices2);
},
});
console.log(self.get('sortedList'));
}
}
});
我仍然没有完美的解决方案,但因为@Aamir Mahmood在评论中要求更新,我将把我的解决方案放在这里,不完美,但现在它工作。
我尝试了我认为每一个可能的解决方案,总是相同的结果,DOM已经打破后一个元素被删除并添加到另一个列表。break并不总是发生在第一次排序之后,但最终还是会发生。
首先我会写我所做的尝试,有一些解决方案在网络上工作的烬的以前的版本,但版本2.0后,解决方案不再工作了。
1)使用组件功能渲染后更新不工作
2)更新后的排序索引也不工作
3)使用值为true/false的计算属性,更新完成后将属性设置为false并立即更改为true不起作用
解决方案是完全删除html ul标签,并重新将其重写为DOM,所有其他解决方案都没有这样做。
我的解决方案是创建计算属性,即数组和只添加一个项目到数组和更新后设置新的数组计算属性。更新后,数组循环将运行,旧的ul标签将被删除,新的将被添加。
模板:
{{#each placeboListComputed as |placeboItem|}}
<ul id="sortable_{{node.id}}" class="sortable_connection">
{{#each sortedList key="index" as |item index|}}
{{li-component
item=item
index=index
}}
{{/each}}
</ul>
{{/each}}
组件,
这不是工作的代码,这只是一个例子,以获得想法。Placebo list是一个计算属性,它是一个数组每当数组被改变时就会循环所以模板会呈现DOM
从一个列表排序到另一个列表后,第一个被触发更新的列表上的项目将从另一个列表接收,然后删除,最后更新列表上的获取项目。因此,在删除项目后,我将该项目保存到垃圾箱,在更新时,我检查给定的项目是否不存在于列表中,但存在于垃圾箱中,我将该项目添加到列表中,并使用计算属性重写内容。
export default Ember.Component.extend({
sortProps: ['index:asc'],
sortedList : Ember.computed.sort('list', 'sortProps'),
placeboList: Ember.A(),
placeboListComputed: Ember.computed('placeboList', function () {
return this.get('placeboList');
}),
init() {
this._super();
this.resetPlacebo();
},
resetPlacebo() {
var list = Ember.A(),
newPlacebo = Placebo.create();
list.pushObject(newPlacebo);
this.set('placeboList', list);
},
updateSortableIndices(items, indices, self) {
self.beginPropertyChanges();
items.forEach((item) => {
var index = indices[Ember.get(item, 'id')];
if (index !== undefined) {
if (Ember.get(item, 'index') !== index) {
Ember.set(item, 'index',index);
}
}
});
self.endPropertyChanges();
},
didRender() {
var self = this;
Ember.$("#sortable_" + this.get('node.id')).sortable({
helper: 'clone',
appendTo: "#append_element",
connectWith: ".sortable_connection",
update: function (event, ui) {
var uiItemId = Ember.$(ui.item).children().attr('data-id'),
uiItemIndex = Ember.$(ui.item).index() + 1;
var item = self.getItem(uiItemId);
var indices = {};
var currentItemIndex = item.index;
Ember.$(this).children().children().each((index, item) => {
indices[Ember.$(item).attr('data-id')] = index + 1;
}).promise().done(function () {
if (!(uiItemId in indices)) {
var trash = self.getTrash(uiItemId);
if (trash !== undefined) {
Ember.$.each(indices, function (id, index) {
if (index >= currentItemIndex ) {
index = index + 1;
indices[id] = index;
}
});
self.removeTrash(uiItemId);
} else {
Ember.set(role, 'index', uiItemIndex);
}
}
self.updateSortableIndices(self.get('list'), indices, self);
});
self.resetPlacebo();
},
receive: function (event, ui) {
var id = ui.item.children().attr('data-id'),
items = self.get('list');
var item= self.getItem(id, true);
items.arrayContentWillChange();
items.pushObject(item);
items.arrayContentDidChange();
},
remove: function (event, ui) {
var item= self.getItem(ui.item.children().attr('data-id')),
items = self.get('list');
var removedIndex = item.index;
items .arrayContentWillChange();
self.pushTrash(item.id, item);
items .removeObject(item);
self.sortRemovedIndex(items , removedIndex);
items .arrayContentDidChange();
}
});
}
这还不是完全测试的解决方案,但我看到它的工作。如果有烬专家,我将很感激看到他的想法或解决这个问题。