我有一个“书籍”页面,最初显示书籍列表。我希望用户能够输入搜索文本,然后更改显示的书籍列表。基于已经在余烬数据存储(客户端)的书籍执行此操作是直截了当的,但我想要做的是执行搜索服务器端。我怎么能这样做?
到目前为止,我的ember控制器中有以下内容
App.BooksIndexController = Ember.ArrayController.extend({
search: '',
actions: {
query: function() {
var search = this.get('search');
var books = this.store.find('books', { search_text: search });
}
}
})
但我不知道接下来该做什么。如何在传递books
的情况下转换到图书清单路线?或者有更多的实现方式,比如创建“搜索”路径/控制器/模板并在该页面上显示结果?
答案 0 :(得分:0)
我刚刚在自己的应用程序中实现了这一点,这可能有点棘手。首先,您需要在应用中添加输入字段,供用户搜索并将其绑定到控制器上的属性:
{{input value=search classNames='form-control' placeholder="Search books"}}
如上所述,它已绑定到控制器的search
属性,并且我已将其设为默认的Bootstrap类form-control
< / p>
现在,让我们在您的控制器中创建一个名为books
的新计算属性:
App.BooksIndexController = Ember.ArrayController.extend({
...
books: function() {
var model = this.get('model');
var search = this.get('search');
var current = 1;
var books = model.filter(function(item) {
var reg = '.*'+search.toLowerCase()+'.*';
var name = item.get('name').toLowerCase();
if(name.match(reg) && current < 20) {
current++;
return true;
}
});
return books;
}.property('search','model.length')
...
});
这样做可以为您建模所有项目并检查name
属性是否与模型中任何books
的名称相匹配。您可以根据需要更改匹配的属性或添加新属性。我不喜欢一次返回所有匹配的项目,因此我添加了current
的限制,以便只返回前20个匹配项。如果您愿意,可以删除它。这样做意味着您将自动显示与商店中已有商品相匹配的商品。
现在,更新您的模板,使其迭代books
代替model
或某些此类内容:
{{#each book in books}}
// do stuff with each book
{{/each}}
这说你太棒了!现在,您在键入时过滤了所有图书,因为只要books
被修改,search
属性就会更新,但现在您需要从API中获取新项目。我们使用另一台计算机属性执行此操作:
searchApi:function() {
var search = this.get('search');
var books = this.store.find('books',{search_text: search});
var model = this.get('model');
books.then(function() { // In my tests, this isn't
model.addObjects(books); // actually necessary, bit I still
}); // like to keep it for clearness
}.observes('search').on('init')
每当修改搜索字段时,这也会触发您的API搜索。然后将任何匹配的项目添加到模型中。这就是为什么我们将model.length
添加到books
计算属性的原因。任何匹配的项目都将添加到模型中并增加其长度,从而触发书籍再次更新。
这应该是你需要的一切。没有新的路由或控制器,只需在索引中正确执行。如果有人对此采取更清洁的方法,我很乐意看到它!