环境:
Ember.VERSION = 1.7.1
DS.VERSION = 1.0.0-beta.14.1
问题: 我试图在最初的应用程序加载时最终呈现视图时运行一些代码,问题是模型尚未加载,因为客户端从服务器获取它。
所以发生的流程(我猜)是这样的:
我想在第3步完成后运行一些代码(工具提示的bootstrap init),但我真的不确定如何。
只是要指出,当我离开并返回到同一路径从服务器获取模型后,一切正常(因为模型从商店返回而不是从服务器返回)
到目前为止我尝试了什么:
How can catch event after template is rendered at EmberJS?
App.ApartmentsView = Ember.View.extend({
didInsertElement: function () {
$('[data-toggle="tooltip"]').tooltip();
}
});
这没有用,因为此时模型长度为0
听取模特改变:
App.ApartmentsRoute = Ember.Route.extend({
model: function () {
return this.store.filter('apartment').then(function (model) {
console.log(model);
return model;
});
}
});
此时,model.content.length = 0
此时我猜这个商店只是创建了模型,并且只在稍后更新它。
我也尝试过监听控制器中的arrayContentDidChange
属性,但此时模型还没有渲染,我可以使用超时,但我认为这是一个糟糕的解决方案。
UPDATE1: 这是模板:
<script type="text/x-handlebars" data-template-name="apartments" id="apartments">
.
.
{{#each }}
<tr>
<td>{{rating}}</td>
<td>{{price}}</td>
<td>{{street}} {{building}} {{city}}</td>
<td class="text-right hidden-print">
<button type="button" class="btn btn-default" aria-label="Left Align" data-toggle="tooltip" data-placement="top" title="Navigate" {{ action 'navigate' }}>
<span class="glyphicon glyphicon-transfer" aria-hidden="true"></span>
</button>
<button type="button" class="btn btn-default" aria-label="Left Align" data-toggle="tooltip" data-placement="top" title="Center Apartment" {{ action 'centerApartment' }}>
<span class="glyphicon glyphicon-screenshot" aria-hidden="true"></span>
</button>
<button type="button" class="btn btn-default" aria-label="Left Align" data-toggle="tooltip" data-placement="top" title="NOT WORKING" {{ action 'setTime' }}>
<span class="glyphicon glyphicon-time" aria-hidden="true"></span>
</button>
<button type="button" class="btn btn-default" aria-label="Left Align" data-toggle="tooltip" data-placement="top" title="NOT WORKING" {{ action 'share' }}>
<span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span>
</button>
{{#link-to 'apartment' this classNames="btn btn-default"}}<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>{{/link-to}}
<div class="btn btn-default" data-toggle="tooltip" data-placement="top" title="Delete Apartment" {{action 'deleteApartment' }}>X</div>
</td>
</tr>
{{/each}}
.
.
</script>
有什么建议吗?
答案 0 :(得分:2)
您对生命周期的描述不正确。它应该是:
Ember进入路线。
调用路由的model
挂钩。
解决了model
挂钩的返回值。
继续进行转换,包括呈现模板并调用其didInsertElement
挂钩。
问题是你的模型钩子正在从过滤器返回一个promise,但是在那时,正如你所发现的那样,商店里还没有记录,因此没有任何过滤。我在您的问题中遗漏的是您何时以及如何期望从服务器加载公寓。 filter
不会为你做那件事。出于我们的目的,我们假设您有一个例程,返回一个名为getApartments
的promise,它确保从服务器加载必要的模型。也许它就像
getApartments: function() {
return this.store.find('apartments');
}
然后用这样的东西替换你的model
钩子:
model: function () {
return this.getApartments() .
then(function(model) {
return this.store.filter('apartment', filterfunc);
})
;
}
现在Ember会等到getApartments
的承诺得到解决,然后使用过滤后的结果作为模型,然后渲染,这样你想要的元素就可以在didInsertElement
钩子中进行操作了
但是,如果稍后将其他公寓添加到商店,这仍然会失败,因为didInsertElement
已在添加元素时运行。要解决这个问题,我建议将您的逻辑移动到一个组件中。无论如何,这可能是一种很好的方法来计算代码。
部件/显示-公寓/ template.hbs
<tr>
<td>{{content.rating}}</td>
...
<button type="button" class="btn btn-default" aria-label="Left Align" data-toggle="tooltip" data-placement="top" title="Navigate" {{ action 'navigate' content}}>
...
</tr>
然后,在组件的JS中,初始化didInsertElement
中的工具提示:
部件/显示-公寓/ component.js
export default Ember.Component.extend({
didInsertElement: function() {
$(this).find('[data-toggle="tooltip"]').tooltip();
}
});
然后在顶级模板中,使用新组件显示每个公寓:
{{#each apartment in model}}
{{show-apartment content=apartment navigate=navigate}}
{{/each}}
现在,每次新公寓进入商店时,过滤后的模型都会反映出来,{{#each}}
将生成新条目,新组件将被创建和呈现,didInsertElement
运行该组件的逻辑以初始化该特定工具提示。
顺便说一句,你的model
挂钩调用store.filter
没有过滤功能。你想用它做什么?
使用isLoaded
是一种黑客和代码气味,在承诺的土地上是不必要的。
答案 1 :(得分:0)
如果您希望在加载模型后才能渲染某些内容,那么我猜您可以在模板中检查isLoaded
键。像这样的东西
template.hbs
{{#if model.isLoaded}}
All the HTML stuff that will be shown only if model is loaded.
{{/if}}
答案 2 :(得分:0)
正如@torazaburo已提到的,问题出在过滤器功能中。简单
model : function(){
return this.store.filter('apartment', {}, function(item){
return true;
});
}
会对你有用。显然,这类似于this.store.find('apartment')
实际上这是一个简单的黑客(包括空对象作为查询),以便在过滤之前从服务器获取数据。
但是,为了确保工具提示在新添加的元素上初始化,@torazaburo提到了更好的方法