我正在NodeJS和AngularJS中构建一个应用程序。
我正在构建一个多列搜索功能,用户可以将搜索关键字输入到单独的搜索框中(位于每列的顶部),并根据列检索结果。
到目前为止,我只有一个搜索框可以同时搜索所有属性。
如何实现多个基于多个属性返回结果的搜索框?
注意:出于性能原因,我想在服务器端实现此功能。 (我知道我可以简单地使用HTML属性| filter:column1 | filter:column2但是如果可能的话就想避免使用这种技术。)
这是我到目前为止的代码。我想我需要传递一些在视图上设置的“searchBy”变量,然后更新搜索方法以通过多个查询/属性对进行搜索。
//Search service factory
//Initialize filtered items and get search results
function search(items, query) {
this.filteredItems = $filter('filter')(items, function (item) {
for(var attr in item) {
if (searchMatch(item[attr], query))
return true;
}
return false;
});
return this.filteredItems;
}
function searchMatch(haystack, needle) {
if (!needle) {
return true;
}
return haystack.toString().toLowerCase().indexOf(needle.toLowerCase()) !== -1;
};
//Controller
vm.filteredItems = vm.search(vm.unfilteredItems, vm.query);
//View
input(type='text', ng-model='vm.query', ng-change='vm.search(vm.unfilteredItems, vm.query)', placeholder='Search')
答案 0 :(得分:0)
我能够通过首先为每个搜索框创建一个对象数组然后使用ng-repeat属性在视图中重复这些框来解决这个问题。
//Controller
var vm = this;
var vm.unfilteredItems; //data source query removed for brevity
//Initialize search inputs
vm.search_by_inputs = [
{search_column: 'id', search_query: ''},
{search_column: 'requester', search_query: ''},
{search_column: 'dataowner', search_query: ''}
];
function initSearch() {
vm.filtered_items = vm.search(vm.unfiltered_items, vm.search_by_inputs);
}
//View
input.input-large.search-query(type='text', value='{{search_by.search_query}}', ng-model='search_by.search_query' ng-change='vm.initSearch()', placeholder='Search')
下一步是循环控制器中的search_by_inputs对象并创建一个新对象,其中只有输入的搜索值输入到视图中的搜索框中。然后在搜索方法中内置"过滤器"组件迭代每个项目,并在该循环内部检查每个搜索项,并使用与该属性匹配的列名称检查该值。
/*
* Create new array of objects with only elements that have search values to optimize loop inside filter
* @search_by_inputs array of objects each has a key search_column and a value search_query
*/
function optimizeSearchProperties(search_by_inputs) {
search_by_properties = [];
for (var i = 0, len = search_by_inputs.length; i < len; i++) {
//If this column input box has query text
if (search_by_inputs[i].search_query) {
search_by_properties.push(search_by_inputs[i]);
}
}
return search_by_properties;
}
/*
* @haystack search item
* @needle search term
*/
function searchMatch(haystack, needle) {
if (!needle) {
return true;
}
return haystack.toString().toLowerCase().indexOf(needle.toLowerCase()) !== -1;
}
/*
* Create filtered items object by filtering search results
* @items original array of objects returned by database query result
* @search_by_inputs array of objects each has a key search_column and a value search_query
*/
function search(items, search_by_inputs) {
var search_by_properties = optimizeSearchProperties(search_by_inputs);
//If there are no search properties input by requester then return all items
if (search_by_properties.length === 0) {
this.filtered_items = items;
return this.filtered_items;
}
this.filtered_items = $filter('filter')(items, function (item) {
var search_result = true;
//Loop over all search by input textboxes
for (var n = 0, len = search_by_properties.length; n < len; n++) {
//If there is no query text
if (!search_by_properties[n].search_query) {
//Continue to next element in array
continue;
//Else if element has a property that matches search input column name
} else if (item[search_by_properties[n].search_column]) {
if (!searchMatch(item[search_by_properties[n].search_column], search_by_properties[n].search_query)) {
search_result = false;
break;
}
}
}
return search_result;
});
return this.filtered_items;
}
我很乐意在优化,性能,技术等方面对此解决方案提供一些反馈。谢谢!