代码之家  ›  专栏  ›  技术社区  ›  Peter Brown

隐藏模板中删除的记录

  •  2
  • Peter Brown  · 技术社区  · 6 年前

    我试图找出是否有更好的方法来隐藏模板中已删除的记录并从计算属性中删除它们。我的ember应用程序正在监听一个web套接字,如果另一个用户删除了一个记录,则会有一个处理程序从存储中删除该记录:

    _handleDelete({id, type: modelName}) {
      const record = get(this, 'store').peekRecord(modelName, id);
    
      if (record) {
        get(this, 'store').deleteRecord(record);
      }
    }
    

    我现在所做的是定义一个计算属性,它过滤掉 isDeleted 是的,并将其用于其他集合:

    allItems: computed.filter('items.@each.isDeleted', function(item) {
      return !get(item, 'isDeleted');
    }),
    

    然后使用此计算属性生成其他计算属性:

    materialCosts: computed.filterBy('allItems', 'proposalCostType', 'material'),
    

    这很好,但我遇到的问题是我没有从这个开始,所以我的许多模板都直接引用hasMany关系( items ),而不是筛选的集合( allItems ). 这是一个巨大的应用程序,所以我必须更新大量的模板才能让它正常工作,而且我认为这没有时间效率。

    我从不希望已删除的记录显示在模板中,也不希望任何计算属性能够引用它们,因此理想情况下,我可以在 项目 关系会自动筛选出已删除的记录,并在删除这些记录时进行更新。

    我在灰烬数据2.14所以也许有一个新的版本可以做到这一点? 更新 -也在2.18上试过,只是想看看它是否是我正在使用的版本。

    编辑

    我尝试了@Gennady Dogaev下面建议的卸载记录,而不是删除它,但是ember给出了监视集合的计算属性的错误。例如,这个:

    approvableItems: computed('items.[]', function() {
      return get(this, 'items').filterBy('isApprovable');
    }),
    

    ... 给我一个错误 isApprovable 无法对未定义的对象调用。

    4 回复  |  直到 6 年前
        1
  •  3
  •   Gennady Dogaev    6 年前

    如果其他用户删除了记录,则 unload 从商店记录。之后,模板将停止呈现它,就好像它从未在存储中一样。

    deleteRecord 在这种情况下,因为它会弄脏ember存储中的数据。你应该打电话 record.save() 打电话之后 删除记录 但它会向API发出http请求,我认为在所描述的情况下您不需要。


    在某些情况下,您可能会遇到神秘的js错误:

    1. 如果尝试将与已删除的id相同的新记录推入存储区
    2. 如果用户尝试重新访问尝试加载已删除/已卸载记录的路由。这可以通过在浏览器中使用后退/前进按钮来实现

    /**
     * This function unloads record from store and clears some private internals to avoid errors when UI tries to read
     * unloaded record from store
     *
     * @see https://discuss.emberjs.com/t/reusing-ids-for-soft-deleted-records/13715/6
     * @param store
     * @param model
     * @param id
     */
    export default function(store, model, id) {
      let record, recordId, modelName;
      if (typeof model === 'object' && typeof model.get === 'function') {
        record = model;
        recordId = model.get('id') || id;
        modelName = model.constructor.modelName;
      } else {
        recordId = id;
        modelName = model;
        record = store.peekRecord(modelName, recordId);
      }
      if (record && !record.isDeleted) {
        store.unloadRecord(record);
      }
      if (recordId) {
        delete store.get('_identityMap')._map[modelName]._idToModel[recordId];
      }
    }
    

    我不知道是否还需要最新版本,但我需要这段代码不久前。

        2
  •  1
  •   lifeart    6 年前

    您可以创建模板助手,并包装 {{#each items}} 喜欢 {{#each (only-active items)}}

        3
  •  1
  •   hrnnvcnt    6 年前

    unless 以及 isDeleted 属性:

    阅读更多关于 已删除 在这里: https://www.emberjs.com/api/ember-data/3.3/classes/DS.Model

    应用程序/routes/todos/index.js

    import Ember from 'ember';
    
    export default Ember.Route.extend(AuthenticatedRouteMixin, {
      model(params) {
        return Ember.RSVP.hash({
          todos: this.store.findAll('todos')
        });
      }
    });
    

    应用程序/controllers/todos/index.js

    export default Controller.extend({
      actions: {
        deleteMe(todo) {
          todo.deleteRecord();
          console.log('deleting todo ' + todo.id); // Just to see if the action works
        }
      }
    });
    

    {{#each model.todos as |todo|}}
      {{#unless todo.isDeleted}}
        <li>{{todo.title}} - <a {{action 'deleteMe' todo}}>delete me</a></li>
      {{/unless}}
    {{/each}}
    

    截图

    unless with IsDeleted

    你可以克隆我的示例代码 https://github.com/hernanvicente/todos-placeholder

        4
  •  1
  •   Mikelemuel    6 年前

    一个简单的解决办法就是做这样的事情。关于你的 template.hbs 做一个每个循环

      {{#each model as |todo|}}
        <li>{{todo.title}} - <a {{action 'removeRecord' todo}}>delete me</a></li>
      {{/each}}
    

    如果不希望在删除记录后立即显示记录,只需执行以下操作。顺便说一下,下面是由ember cli 1.13引用的

    removeRecord(todo) {
      todo.destroyRecord().then(() => {
        this.send('reloadModel');
      });
    }
    

    reloadModel是在删除记录后重新加载记录。但是,如果您的后端在发送删除此类记录的请求后确实删除了该记录,则它将在 removeRecord 正在请求您的API。希望这对你有帮助。