我是Ember的新手,我正在尝试设置文件夹列表。当您单击文件夹旁边的图标时,它将加载(即查找('folder',folder_id))子文件夹。如果顶级文件夹有16个子文件夹,我试图在这16个文件夹上设置一个属性,因为它们已经完成加载 - 所以如果其中一个子文件夹的模型完成加载,我想设置一个属性在其他十五个文件夹仍然被检索和序列化时。
在我的文件夹模型中:
import DS from 'ember-data';
export default DS.Model.extend({
files: DS.hasMany('file'),
children: DS.hasMany('folder', { inverse: 'parent', async: true }),
parent: DS.belongsTo('folder', {inverse: 'children'}),
name : DS.attr('string'),
nodeId : DS.attr('string'),
classId : DS.attr('string'),
parentId: DS.attr('string'),
contents: DS.attr(),
isVisible: DS.attr('boolean'),
childName: DS.attr('string')
});
在我的模板/视图中:
{{#each child in children}}
{{#if child.isLoading}}
Loading -->
{{else}}
{{setChildProperty}}
{{/if}}
{{/each}}
在我的控制器中:
import Ember from 'ember';
export default Ember.Controller.extend({
children: function() {
var model = this.get('model');
var children = model.get('children');
return children;
}.property(),
setChildProperty: function(){
// how can I know, here in the controller, what the index is for
// the child that triggered this function, so that I can set a
// property on it without getting some type of
// 'didSetProperty / root.state.loading' error.
// The code below will cause errors because not all of the
// children have finished loading:
// var model = this.get('model');
// var self = this;
// var children = model.get('children');
// var contents = model.get('contents');
//
// children.forEach(function(item, index){
// var folderName = contents[index].folder;
// item.set('name',folderName);
// });
}.property('children.@each.isLoading'),
});
我的Ember-CLI版本是0.1.15
非常感谢任何帮助。
更新
关于mpowered的解决方案,真正的问题是我的文件夹模型的性质,因为文件夹模型没有name属性,而是有一个子名称列表。并且由于当用户单击子文件夹时异步检索子关系,我需要从另一个数组获取子文件夹名称,该数组具有相同的索引。所以使用mpowered的解决方案我的问题就是这样:
foldr: {{folder.id}}<br>
{{#each child in folder.children}}
{{#view 'toggle-list'}}
<i {{bind-attr id="child.id"}} class="fa fa-caret-right"></i>
{{/view}}
Index: {{_view.contentIndex}}
<!-- I need to be able to echo the above index in the
folder.contents array to get the child name.
-->
<!-- these work when uncommented, but I need a dynamic solution
name: {{folder.contents.[1].folder}}
name: {{folder.contents.1.folder}}
-->
<!-- None of these work:
name:{{!folder.contents.[_view.contentIndex].folder}}
name:{{!folder.contents.index.folder}}
name:{{!folder.contents.[index].folder}}
name:{{!folder.contents.{{!_view.contentIndex}}.folder}}
-->
Child:{{child.id}}..
<br>
<div {{bind-attr id="child.childName"}} class="folder-child hidden">
{{#if child.isVisible}}
isVisible is true<br>
{{folder-tree-component folder=child}}
{{/if}}
</div>
{{/each}}
我还应该注意到我使用的是PODS结构,我无法控制从服务器获取的JSON响应,以填充我的模型(当然除了Ember序列化器)。
答案 0 :(得分:0)
有很多事情与此有关。
首先,属性不是动作。当你获得一个属性时,你并不想改变一个对象的状态,除非你有很好的理由这样做,或者你正在实现一个getter / setter模式。删除setChildProperty
,因为这一切都很糟糕。在模板中,您应该只显示属性,而不是尝试用它“做”任何事情。
其次,这应该可以作为一个组件创建,因为它听起来像你在这里的递归结构可以很好地适用于可重用的组件。像folder-tree-component.hbs
:
{{folder.name}}
{{#each child in folder.children}}
{{folder-tree-component folder=child}}
{{/each}}
在你的主要路线中:
{{folder-tree-component folder=model}}
// Or, alternatively
{{#each child in model.children}}
{{folder-tree-component folder=child}}
{{/each}}
如果我理解正确,你需要模型上的计算属性,而不是在完成加载时在模型(或控制器/组件)上“设置”某些东西。当请求该属性时,它将计算该值并缓存它以防您再次请求它。在您的模型上:
name: function() {
// something with this.get('contents')
}.property('contents', 'otherDependency') // <- These will tell Ember to recompute the property when changed
在尝试解决这个问题之前,我会更多地了解ember基础知识,有一些非常简单但至关重要的事情要了解Ember如何滴答,而文件树并不是最简单的实现。