我试图找出是否有更好的方法可以从模板中隐藏已删除的记录,并将其从计算的属性中删除。我的ember应用正在监听Web套接字,如果另一个用户删除了一条记录,则有一个处理程序将从存储中删除该记录:
_handleDelete({id, type: modelName}) {
const record = get(this, 'store').peekRecord(modelName, id);
if (record) {
get(this, 'store').deleteRecord(record);
}
}
我当前正在做的是定义一个计算属性,该属性会过滤掉isDeleted
为true的所有记录,并将其用于其他集合:
allItems: computed.filter('items.@each.isDeleted', function(item) {
return !get(item, 'isDeleted');
}),
然后我正在使用此计算属性来构建其他计算属性:
materialCosts: computed.filterBy('allItems', 'proposalCostType', 'material'),
这很好,但是我遇到的问题是我不是从这个开始的,所以我的许多模板都直接引用hasMany关系(items
),而不是过滤后的集合({ {1}})。这是一个巨大的应用程序,因此我必须更新大量模板才能使其正常运行,而且我认为这样做并不省时。
我从不希望已删除的记录显示在模板中,也不希望任何计算出的属性能够引用它们,因此,理想情况下,我将能够执行allItems
关系自动过滤的操作删除记录,并在删除记录时进行更新。
我正在使用Ember Data 2.14,所以也许有更新的版本可以做到这一点? 更新-还尝试在2.18上查看它是否是我使用的版本。
修改
我尝试了@Gennady Dogaev在下面建议的卸载记录而不是删除记录的方法,但是ember给我的错误是正在监视集合的计算属性。例如,这个:
items
...给我一个错误,无法在未定义的对象上调用approvableItems: computed('items.[]', function() {
return get(this, 'items').filterBy('isApprovable');
}),
。
答案 0 :(得分:3)
如果其他用户删除了记录,则从存储中unload条记录会更正确。之后,模板将停止呈现它,就像它从未在商店中一样。
在这种情况下,我不建议使用deleteRecord
,因为它会弄脏余烬存储中的数据。您应该在调用record.save()
之后再调用deleteRecord
,但是在描述的情况下,它将向API发送http请求,我认为您不希望这样做。
在某些情况下,您可能会遇到js隐秘错误:
如果在这些情况下遇到一些错误,请尝试使用以下方法卸载记录:
/**
* 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];
}
}
我不知道是否仍需要最新版本,但不久前我需要此代码。
答案 1 :(得分:1)
您可以创建模板帮助程序,并像{{#each items}}
一样包装{{#each (only-active items)}}
答案 2 :(得分:1)
您可以尝试结合内置帮助器unless
和isDeleted
属性,直接在视图上排除已删除的记录:
在https://www.emberjs.com/api/ember-data/3.3/classes/DS.Model上了解有关isDeleted
的更多信息
app / 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')
});
}
});
app / 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
}
}
});
app / templates / todos / index.hbs
{{#each model.todos as |todo|}}
{{#unless todo.isDeleted}}
<li>{{todo.title}} - <a {{action 'deleteMe' todo}}>delete me</a></li>
{{/unless}}
{{/each}}
屏幕截图
克隆我的示例代码答案 3 :(得分:1)
一个简单的解决方案是做这样的事情。在您的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用于在删除记录后重新加载记录。但是,如果您的后端在发送删除记录的请求后确实删除了该记录,则一旦向您的API请求removeRecord
,它就会删除您的数据。希望对您有帮助。