实施 ember 服务器端搜索
implementing ember server side search
我有一个 "books" 页面,最初显示的是图书列表。我希望用户能够输入搜索文本,然后更改显示的图书列表。根据 embers 数据存储(客户端)中已有的书籍执行此操作很简单,但我想做的是执行搜索服务器端。我该怎么做?
到目前为止,我的 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
转换到书籍列表路由?或者是否有更 ember 的方式来做到这一点,比如创建 "search" route/controller/template 并在该页面上显示结果?
我刚刚在我自己的应用程序中实现了它,它可能有点棘手。首先,您需要在您的应用中添加一个输入字段,供用户用于搜索并将其绑定到控制器上的 属性:
{{input value=search classNames='form-control' placeholder="Search books"}}
正如你在上面看到的,它绑定到你的控制器的 search
属性 我已经给它默认的 Bootstrap class form-control
现在,让我们在您的控制器中创建一个名为 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
计算的 属性。任何匹配的项目都将添加到模型中并增加其长度,从而触发书籍再次更新。
这应该是您需要的一切。没有新的路线或控制器,只需在索引中正确执行即可。如果有人对此有更清晰的方法,我很乐意看到它!
我有一个 "books" 页面,最初显示的是图书列表。我希望用户能够输入搜索文本,然后更改显示的图书列表。根据 embers 数据存储(客户端)中已有的书籍执行此操作很简单,但我想做的是执行搜索服务器端。我该怎么做?
到目前为止,我的 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
转换到书籍列表路由?或者是否有更 ember 的方式来做到这一点,比如创建 "search" route/controller/template 并在该页面上显示结果?
我刚刚在我自己的应用程序中实现了它,它可能有点棘手。首先,您需要在您的应用中添加一个输入字段,供用户用于搜索并将其绑定到控制器上的 属性:
{{input value=search classNames='form-control' placeholder="Search books"}}
正如你在上面看到的,它绑定到你的控制器的 search
属性 我已经给它默认的 Bootstrap class form-control
现在,让我们在您的控制器中创建一个名为 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
计算的 属性。任何匹配的项目都将添加到模型中并增加其长度,从而触发书籍再次更新。
这应该是您需要的一切。没有新的路线或控制器,只需在索引中正确执行即可。如果有人对此有更清晰的方法,我很乐意看到它!