我一直在尝试使用没有余烬数据的Emberjs。我正在尝试连接到现有的JSON (但不是REST) API。
我正在尝试加载缩略图图像网格,并通过点击它来显示所选图像的高分辨率预览。
API有单独的调用来获取文件集合以获取单个文件的详细信息。显然,我想避免拨打100多个电话来获取预览高分辨率图像网址。因此,我的App.File.find和App.File.findAll使用不同的API调用。
IMS.api.call
是围绕jQuery.ajax
的简单包装器,它返回一个promise。
问题:网格加载正常(/#/files/
)但是,如果单击单个图像,预览将使用缩略图而非预览图像(/#/files/11659315501
) 。但是,如果我刷新浏览器,那么我会得到一个高分辨率的版本。
添加一些日志记录我发现永远不会调用第一个版本App.File.find
。在刷新时,它会被调用一次。
我尝试过的事情:
我添加了一个计算属性,可以单独调用以获取高分辨率网址:
bigUrl: function(){
var id = this.get('content.id');
preview = App.File.find(id);
return preview.url;
}.property('id')
但是jQuery调用返回的defer在视图渲染时没有加载,因此bigUrl未定义。所以我尝试在承诺中包装它,但Ember抱怨计算属性不能返回一个承诺。
我到处寻找如何鼓励余烬打电话App.File.find
,但无济于事。
有什么想法吗?
window.App = Ember.Application.create();
App.Router.map(function() {
this.resource('files',function(){
this.resource('file',{path:':file_id'});
});
});
App.IndexRoute = Ember.Route.extend({
redirect: function(){
this.transitionTo('files');
}
});
App.FilesRoute = Ember.Route.extend({
model: function() {
return App.File.findAll();
}
});
App.FileRoute = Ember.Route.extend({
model: function(args) {
return App.File.find(args.file_id);
}
});
App.File = Ember.Object.extend({});
App.File.reopenClass({
find: function(id){
return IMS.api.call("Files.GetAssetDetails",{"assetId":id}).then(
function(response) {
file = response.outParams;
return App.File.create({'id':file.id,'filename':file.filename,"url":file.panoramicUrl});
}
);
},
findAll: function() {
return IMS.api.call("Files.GetAssetsForParent",{"containerId":11659314773}).then(
function(response) {
var files = [];
response.outParams.forEach(function (file) {
files.push(App.File.create({'id':file.id,'filename':file.filename,"url":file.thumbUrl}));
});
return files;
}
);
},
});
[更新]
观点如下:
应用:
<script type="text/x-handlebars" data-template-name="application">
<div class="row">
<div class="twelve columns">
<h1>/pics/</h1>
<hr>
{{outlet}}
</div>
</div>
</script>
文件:
<script type="text/x-handlebars" data-template-name="files">
<div class="row">
<div class="six columns">
{{outlet}}
</div>
<div class="six columns" id='chooser'>
{{#each file in model}}
<div style='float:left'>
<div>
{{#linkTo file file}}
<img {{bindAttr src="file.url"}} style='width:100px;height:100px;'>
{{/linkTo}}
</div>
</div>
{{/each}}
</div>
</div>
</script>
文件
<script type="text/x-handlebars" data-template-name="file">
{{log id}}{{log url}}
<div>
<img {{bindAttr src="url"}} style='width:400px;height:400px;'>
</div>
<div>
{{id}}
</div>
</script>
答案 0 :(得分:2)
要在每次路线更改时强制重新加载模型,您需要从setupController
拨打电话。
每次路线更改时都会调用setupController
。我选择将模型称为函数,而不是重复App.File.find
调用。
App.FileRoute = Ember.Route.extend({
setupController: function(controller,model){
console.log("setupController",controller,model);
controller.set('model',this.model({file_id:model.id}));
},
model: function(params) {
return App.File.find(params.file_id);
}
});
不幸的是,如果您要返回承诺,这不起作用。为了使它工作,你必须返回一个对象,并承诺稍后填写它。
find: function(id){
file = App.File.create({});
IMS.api.call("Files.GetAssetDetails",{"assetId":id,"fields":{"metadata":true}}).then(function(response) {
file.setProperties({'id':response.outParams.id,'filename':response.outParams.filename,"url":response.outParams.panoramicUrl,"metadata":response.outParams.metadata});
}
);
return file;
},
这确实会留下一个偶然的错误:
TypeError:'undefined'不是对象(评估'response.outParams.id')
这是由setupController
未从模型中获取有效ID,然后将undefined处理为第一次调用它而导致的。
必须有更好的方法从路线中获取身份证......任何人?
<强> [UPDATE] 强>
以下是我停止错误的方法:
setupController: function(controller,model){
if(model.isLoaded == false){
controller.set('model',model);
} else {
controller.set('model',this.model({file_id:model.id}));
}
},
我在我的find函数中添加了一个'.isLoaded'标志:
find: function(id){
file = App.File.create({isLoaded: false});
IMS.api.call("Files.GetAssetDetails",{"assetId":id,"fields":{"metadata":true}}).then(function(response) {
file.setProperties({'id':response.outParams.id,'filename':response.outParams.filename,"url":response.outParams.panoramicUrl,"metadata":response.outParams.metadata});
file.set('isLoaded', true);
});
return file;
},