【问题标题】:Delete item after sorting jQuery UI with Ember使用 Ember 对 jQuery UI 进行排序后删除项目
【发布时间】:2016-09-23 14:45:43
【问题描述】:

我正在使用带有 jQ​​uery 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'));
        }
    }
});

【问题讨论】:

  • 删除后是否打印console.log(self.get('sortedList'));排序列表?
  • @kumkanillam 是的,打印的列表很好,但 DOM 是错误的。
  • 只需删除此行list: Ember.ArrayProxy.create({content: Ember.A()}) 并在init() 中包含以下行 - this.set('list',[]);我的意思是你可以用普通数组而不是 ArrayProxy 试试这个。ArrayProxy 有什么具体原因吗?。
  • @kumkanillam 我尝试使用普通的 [],使用 Ember.A 并始终得到相同的结果。我删除了这条线,并且行为相同。这是排序后 DOM 的样子link。我在
  • 标签之前添加了额外的 {{item.id}} 以查看每个标签的工作方式,并且每个订单与
  • 标签不同。删除第 3 项后,第 2 项也会从 DOM 中删除,因为它在 3 之后。
  • 也许你可以试试插件github.com/jgwhite/ember-sortable或者这个stack overflow question
  • 标签: javascript sorting jquery-ui ember.js


    【解决方案1】:

    我的问题仍然没有完美的解决方案,但因为@Aamir Mahmood 在评论中要求更新,我将把我的解决方案放在这里,虽然不完美,但现在它可以工作。

    我尝试了所有可能的解决方案,结果总是相同,在一个元素被删除并添加到另一个列表后,DOM 已经损坏。中断并不总是在第一次排序之后发生,但最终确实发生了。

    首先我会写下我所做的尝试,网络上有一些解决方案可以在以前版本的 ember 上运行,但在 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}}
    

    组件,

    这不是有效的代码,这只是获取想法的示例。安慰剂列表是计算属性,它是数组,每次更改数组时都会循环,因此模板将重新渲染 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();
            }
        });
    }
    

    这还不是经过全面测试的解决方案,但我看到它有效。如果有一些 Ember 专家,我会很感激看到他对这个问题的想法或解决方案。

    【讨论】:

      猜你喜欢
      相关资源
      最近更新 更多
      热门标签