隐藏模板中已删除的记录

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了隐藏模板中已删除的记录相关的知识,希望对你有一定的参考价值。

我试图弄清楚是否有更好的方法来隐藏模板中的已删除记录并从计算属性中删除它们。我的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)。这是一个巨大的应用程序,所以我必须更新TON模板才能使其工作,我认为这不是时间效率。

我从不希望删除的记录在模板中显示,也不希望任何计算属性能够引用它们,所以理想情况下我可以做一些items关系自动过滤掉已删除记录并在更新时更新的内容他们被删除了。

我在使用Ember Data 2.14,所以也许有更新的版本可以做到这一点?更新 - 也尝试在2.18只是为了看看它是否是我正在使用的版本。

编辑

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

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

...给我一个错误,不能在未定义的对象上调用isApprovable

答案

如果其他用户删除了记录,那么来自商店的unload记录会更正确。之后,模板将停止渲染,就像它从未在商店中一样。

在这种情况下,我不建议使用deleteRecord,因为它会污染ember存储中的数据。您应该在调用record.save()之后调用deleteRecord,但它会向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];
  }
}

我不知道它是否仍然需要最新版本,但我不需要这个代码。

另一答案

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

另一答案

您可以尝试直接在视图中排除已删除的记录,并结合内置帮助程序unlessisDeleted属性:

在这里阅读更多关于isDeleted的信息:https://www.emberjs.com/api/ember-data/3.3/classes/DS.Model

应用程序/路由/待办事项/ index.js

import Ember from 'ember';

export default Ember.Route.extend(AuthenticatedRouteMixin, {
  model(params) {
    return Ember.RSVP.hash({
      todos: this.store.findAll('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
    }
  }
});

应用程序/模板/待办事项/ index.hbs

{{#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克隆我的示例代码

另一答案

一个简单的解决方案是做这样的事情。在你的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请求后删除您的数据。希望这可以帮到你。

以上是关于隐藏模板中已删除的记录的主要内容,如果未能解决你的问题,请参考以下文章

在android中显示隐藏片段

使用触发器归档多个表中已删除的记录

使用删除与隐藏时未调用自定义动画

有没有办法恢复一个月前删除的Mysql中已删除的行

如何隐藏/删除操作列项?

打开键盘隐藏片段下方的工具栏