Ember.js过滤来自动态路由的数据
Ember.js filtering data from a dynamic route
我正在尝试使用动态路由根据搜索字符串筛选数据。当使用控制器的transitionToRoute
函数时,路由中的模型数据会正确返回到视图,但是,当直接导航到url或刷新页面时,由于模型中数据的长度为0,因此不会执行所有forEach调用。
我有一种感觉,这是因为数据是异步加载的,但我不知道如何延迟forEach循环和视图的渲染,直到find
的promise得到解决,forEach环路完成。
这是我的路由器的model
功能:
model : function( params ){
var lists = App.List.find( ), //gets all the lists
query = params.query, //query string from url
re = new RegExp( query, 'i' );
this.set( 'query', query );
return lists.forEach( function( list ){
var cards = list.get( 'cards' ).forEach( function( card ){
//the view has a class bound to the hide property of each card
card.set( 'hide',
( query.length ) ? !( re.test( card.get( 'description' ) ) ) : false
);
} );
return list;
});
}
当用户使用查询字符串为#/search/red
的url点击应用程序时,我只希望返回其中包含"红色"的卡片。
我刚刚重新发现了这个问题,这是我试图给出的答案。正如我在评论中已经提到的,这是我的基本想法:
具有计算属性:
- 不要在模型挂钩中进行过滤,只需返回列表即可
- 在路由的控制器上设置查询(名为SearchController?)
- 在控制器中作为计算属性进行筛选
与观察员:(更接近您的原始代码)
- 不要在模型挂钩中进行过滤,只需返回列表即可
- 在路由的控制器上设置查询(名为SearchController?)
- 将逻辑从模型挂钩中隐藏卡片,并将其作为控制器上的观察者来实现
最好的方法是使用计算属性,但我不确定如何进行(Ember团队表示,计算属性通常会带来更好的代码)。因此,这里是使用Observer方法的代码的粗略草图。这应该可以作为一个开始:
路线:
model : function( params ){
this.set( 'query', params.query );
return App.List.find(); //gets all the lists
},
setupController : function(controller, model) {
this._super(controller, model);
// setupController is a good location to setup your controller
controller.set("query", this.get("query"));
}
控制器:
App.SearchController = Ember.ArrayController.extend({
query : '',
// this observer will fire:
// 1.: every time a list object is added or removed from the underlying array
// 2.: the query changes
modelAndQueryObserver : function(){
re = new RegExp( this.get("query"), 'i' );
return this.get("model").forEach( function( list ){
var cards = list.get( 'cards' ).forEach( function( card ){
//the view has a class bound to the hide property of each card
card.set( 'hide',
( query.length ) ? !( re.test( card.get( 'description' ) ) ) : false
);
} );
return list;
});
}.observes("model.@each", "query")
});
这里有一个实现,其中控制器的模型和内容属性在相应路由的setupController//strong>挂钩处明显分离。
我在一个单独的文件中列出了不同颜色的球。
balls.js
[
{"id":1,"color":"darkred"},
{"id":2,"color":"lightred"},
{"id":3,"color":"darkgreen"},
{"id":4,"color":"lightgreen"},
{"id":5,"color":"darkblue"},
{"id":6,"color":"lightblue"}
]
App.js
App = Ember.Application.create();
App.Router.map(function() {
this.resource('balls',{path:"/balls/:color"});
});
App.BallsRoute = Ember.Route.extend({
model: function(params) {
return params;
},
serialize:function(model){return {color:model.color}},
setupController:function(cont,model){
var balls=Em.A();
if(!App.Balls)
App.Balls=$.getJSON("/start/js/balls.js");
App.Balls.then(function(json){
var re=new RegExp(model.color)
balls.setObjects(json);
var filtered =balls.filter(function(o,i){return re.test(o.color);});
cont.set('content',filtered);
});
}
});
App.ApplicationController=Em.Controller.extend({
searches:[{color:"red"},{color:"blue"},{color:"green"}]
});
App.BallsController=Em.ArrayController.extend({
});
HTML
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
<nav>
{{#each item in searches}}
{{#link-to "balls" item}} {{item.color}} {{/link-to}}
{{/each}}
</nav>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="balls">
<ul>
{{#each controller}}
<li>{{color}}</li>
{{/each}}
</ul>
</script>
我不使用Ember数据,因为我对它不舒服。
请检查此纸盒
您对异步调用引起的问题是正确的。当您直接输入路由时,从find调用返回的对象是promise,而不是live列表。你需要等待承诺解决后再处理它。
像这样的东西应该起作用:
model : function( params ){
var lists = App.List.find( ), //gets all the lists
query = params.query, //query string from url
re = new RegExp( query, 'i' );
this.set( 'query', query );
// 'lists' is a promise, once it has resolved we can deal with it
lists.then(function(realLists){ // realLists is a real collection of models
realLists.forEach(function(list){
list.get('cards').forEach( function( card ){
//the view has a class bound to the hide property of each card
card.set( 'hide',
( query.length ) ? !( re.test( card.get( 'description' ) ) ) : false
);
});
});
});
// return the 'lists 'promise immediately
// maybe before the 'lists.then' function above has run
// Ember will resolve the promise for you and set up the controller correctly
return lists;
}
请注意,当您调用上面的list.get('cards')
时,根据您的加载方法(侧面加载与额外的http调用),您实际上可能会得到一个promise,而不是一组卡片。如果是这样的话,你可以使用同样的技术。
cards = list.get('cards');
cards.then(function(realCards){
realCards.forEach(...);
});
同样值得注意的是,在最新版本的Ember Data中,查找方法发生了变化。你应该做this.store.find('list')
而不是App.List.find( )
。(过渡指南提供了更多关于突破性变化的信息。https://github.com/emberjs/data/blob/master/TRANSITION.md)
- Angular JS和Node路由/布线-仅在页面刷新后显示数据
- 使用iron路由器服务器路由中的数据渲染模板
- Angular2路由-将数据从父组件传递到子组件
- Hapi-js重定向到另一个带有额外请求数据的路由
- 在Node.js中将数据传递到子路由时出现问题
- 在Emberjs中设置从路由到控制器的数据错误
- 如何通过Websockets路由不同的数据类型
- 数据切换=“;下拉菜单”;激活路由重定向,而不是yeoman中的下拉菜单
- 使用路由的解析数据进行角度注入
- 在路由 angularjs/expressjs 之间传递数据
- AngularJS ui-router:如何全局解析所有路由的典型数据
- Ember JS - 从路由操作更新/刷新模型数据
- 重新解析角度路由数据并保持数据同步
- meteorjs:简单的可重用模板,使用Iron Router具有特定于路由的数据上下文
- 角度 UI 路由器 - 使用路由传递动态数据
- AngularJS:在模板外部获取路由解析数据
- 如何在刷新时将持久数据保存在角度路由服务中
- Angular 2 RC Final——从service动态加载路由数据
- 铁路由器:在路由器功能中访问路由数据
- 我需要路由数据在客户端之间的节点客户端正确连接的用户