Фильтрация по нескольким конкретным свойствам модели в AngularJS (в отношении OR)

Посмотрите на пример здесь: http://docs.angularjs.org/апи /ng.filter: фильтр

Вы можете искать по любому из свойств телефона, используя <input ng-model="search">, и вы можете искать только по имени, используя <input ng-model="search.name">, и результаты соответствующим образом фильтруются по имени (ввод номера телефона не возвращает никаких результатов, как ожидалось).

Допустим, у меня есть модель со свойством «name», свойством «phone» и свойством «secret», как мне отфильтровать по обоим по «name» и «name» телефон "свойства, а не " секретное "свойство? Таким образом, по сути, пользователь может ввести имя или номер телефона, и ng-repeat будет фильтроваться правильно, но даже если пользователь введет значение это равняется части «секретного» значения, оно ничего не вернет.

Спасибо.

104 голоса | спросил Matt Reyer 4 72012vEurope/Moscow11bEurope/MoscowSun, 04 Nov 2012 08:36:53 +0400 2012, 08:36:53

11 ответов


0

Вот плункер

Новый плункер с более чистым кодом & где элементы запроса и поиска не чувствительны к регистру

Основная идея - создать функцию фильтра для достижения этой цели.

Из официального документа

  Функция

: функция предиката может использоваться для написания произвольных фильтров.   Функция вызывается для каждого элемента массива. Конечный результат   массив тех элементов, для которых предикат вернул true.

<input ng-model="query">

<tr ng-repeat="smartphone in smartphones | filter: search "> 

$scope.search = function(item) {
    if (!$scope.query || (item.brand.toLowerCase().indexOf($scope.query) != -1) || (item.model.toLowerCase().indexOf($scope.query.toLowerCase()) != -1) ){
        return true;
    }
    return false;
};

Обновление

Некоторые люди могут беспокоиться о производительности в реальном мире, и это правильно.

В реальном мире мы, вероятно, сделали бы этот своего рода фильтр с контроллера.

Вот подробное сообщение , показывающее, как сделать это.

короче говоря, мы добавляем ng-change для ввода для мониторинга новых изменений поиска

и затем активировать функцию фильтра.

ответил maxisam 4 72012vEurope/Moscow11bEurope/MoscowSun, 04 Nov 2012 09:20:36 +0400 2012, 09:20:36
0

Вы можете передать объект в качестве параметра в выражение фильтра, как описано в справочнике по API , Этот объект может выборочно применять интересующие вас свойства, например:

<input ng-model="search.name">
<input ng-model="search.phone">
<input ng-model="search.secret">
<tr ng-repeat="user in users | filter:{name: search.name, phone: search.phone}">

Вот вам Плункер

Heads up ... этот пример прекрасно работает с AngularJS 1.1.5, но не всегда так же хорошо в 1.0.7. В этом примере 1.0.7 будет инициализироваться со всем отфильтрованным, а затем работать, когда вы начнете использовать входы. Он ведет себя так, как будто на входах есть несоответствующие значения, даже если они начинаются пустыми. Если вы хотите сохранить стабильные выпуски, попробуйте это в своей ситуации, но в некоторых сценариях может потребоваться использовать решение @ maxisam до выпуска 1.2.0.

ответил Anson 19 J0000006Europe/Moscow 2013, 18:07:33
0

Я вдохновился ответом @ maxisam и создал свою собственную функцию сортировки, и я хотел бы поделиться ей (потому что мне скучно).

Ситуация Я хочу отфильтровать множество автомобилей. Выбранные свойства для фильтрации: имя, год, цена и км. Цена недвижимости и км являются числами (отсюда следует использование .toString). Я также хочу контролировать заглавные буквы (следовательно, .toLowerCase). Также я хочу иметь возможность разделить мой запрос фильтра на разные слова (например, учитывая фильтр 2006 Acura, он находит совпадения 2006 с годом и Acura с именем).

Функция, которую я передаю фильтру

        var attrs = [car.name.toLowerCase(), car.year, car.price.toString(), car.km.toString()],
            filters = $scope.tableOpts.filter.toLowerCase().split(' '),
            isStringInArray = function (string, array){
                for (var j=0;j<array.length;j++){
                    if (array[j].indexOf(string)!==-1){return true;}
                }
                return false;
            };

        for (var i=0;i<filters.length;i++){
            if (!isStringInArray(filters[i], attrs)){return false;}
        }
        return true;
    };
ответил NicolasMoise 28 42013vEurope/Moscow11bEurope/MoscowThu, 28 Nov 2013 22:25:29 +0400 2013, 22:25:29
0

Если вы открыты для использования сторонних библиотек, вам могут пригодиться Angular Filters с хорошим набором фильтров:

https://github.com/a8m/angular-filter#filterby

collection | filterBy: [prop, nested.prop, etc..]: search
ответил Khashayar 24 AM00000030000005731 2015, 03:07:57
0

Надеюсь, этот ответ поможет, Несколько Фильтр значений

И рабочий пример в этой скрипке

arrayOfObjectswithKeys | filterMultiple:{key1:['value1','value2','value3',...etc],key2:'value4',key3:[value5,value6,...etc]}
ответил Nirmal Kumar VeluPillai 16 Jpm1000000pmThu, 16 Jan 2014 22:33:06 +040014 2014, 22:33:06
0

Здесь есть множество хороших решений, но я бы предложил пойти другим путем. Если поиск является наиболее важным, и свойство «secret» вообще не используется в представлении; Мой подход для этого состоит в том, чтобы использовать встроенный угловой фильтр со всеми его преимуществами и просто отобразить модель на новый массив объектов.

Пример из вопроса:

$scope.people = members.map(function(member) { 
                              return { 
                                name: member.name, 
                                phone: member.phone
                              }});

Теперь в html просто используйте обычный фильтр для поиска обоих этих свойств.

<div ng-repeat="member in people | filter: searchString">
ответил Siddharth Singh 20 FebruaryEurope/MoscowbSat, 20 Feb 2016 15:05:50 +0300000000pmSat, 20 Feb 2016 15:05:50 +030016 2016, 15:05:50
0

http://plnkr.co/edit/A2IG03FLYnEYMpZ5RxEm?p=preview

Вот поиск с учетом регистра, который также разделяет ваш поиск на слова для поиска в каждой модели. Только когда он найдет пробел, он попытается разбить запрос на массив, а затем искать каждое слово.

Возвращает true, если каждое слово есть хотя бы в одной из моделей.

$scope.songSearch = function (row) {
    var query = angular.lowercase($scope.query);
    if (query.indexOf(" ") > 0) {
        query_array = query.split(" ");
        search_result = false;
        for (x in query_array) {
            query = query_array[x];
            if (angular.lowercase(row.model1).indexOf(query || '') !== -1 || angular.lowercase(row.model2).indexOf(query || '') !== -1 || angular.lowercase(row.model3).indexOf(query || '') !== -1){
                search_result = true;
            } else {
                search_result = false;
                break;
            }
        }
        return search_result;
    } else {
        return (angular.lowercase(row.model1).indexOf(query || '') !== -1 || angular.lowercase(row.model2).indexOf(query || '') !== -1 || angular.lowercase(row.model3).indexOf(query || '') !== -1);
    }
};
ответил Tom Quinlan 17 AM000000110000002731 2015, 11:43:27
0

Довольно простой подход с использованием filterBy в angularJs

Для работы plnkr перейдите по этой ссылке

ответил CredibleAshok 3 Mayam17 2017, 10:13:00
0

Мне нравится, когда все просто. Мне нужно было сгруппировать по International, отфильтровать по всем столбцам, отобразить счетчик для каждой группы и скрыть группу, если элементов не было.

Кроме того, я не хотел добавлять пользовательский фильтр только для чего-то простого.

        <tbody>
            <tr ng-show="fusa.length > 0"><td colspan="8"><h3>USA ({{fusa.length}})</h3></td></tr>
            <tr ng-repeat="t in fusa = (usa = (vm.assignmentLookups | filter: {isInternational: false}) | filter: vm.searchResultText)">
                <td>{{$index + 1}}</td>
                <td ng-bind-html="vm.highlight(t.title, vm.searchResultText)"></td>
                <td ng-bind-html="vm.highlight(t.genericName, vm.searchResultText)"></td>
                <td ng-bind-html="vm.highlight(t.mechanismsOfAction, vm.searchResultText)"></td>
                <td ng-bind-html="vm.highlight(t.diseaseStateIndication, vm.searchResultText)"></td>
                <td ng-bind-html="vm.highlight(t.assignedTo, vm.searchResultText)"></td>
                <td ng-bind-html="t.lastPublished | date:'medium'"></td>
            </tr>
        </tbody>
        <tbody>
            <tr ng-show="fint.length > 0"><td colspan="8"><h3>International ({{fint.length}})</h3></td></tr>
            <tr ng-repeat="t in fint = (int = (vm.assignmentLookups | filter: {isInternational: true}) | filter: vm.searchResultText)">
                <td>{{$index + 1}}</td>
                <td ng-bind-html="vm.highlight(t.title, vm.searchResultText)"></td>
                <td ng-bind-html="vm.highlight(t.genericName, vm.searchResultText)"></td>
                <td ng-bind-html="vm.highlight(t.mechanismsOfAction, vm.searchResultText)"></td>
                <td ng-bind-html="vm.highlight(t.diseaseStateIndication, vm.searchResultText)"></td>
                <td ng-bind-html="vm.highlight(t.assignedTo, vm.searchResultText)"></td>
                <td ng-bind-html="t.lastPublished | date:'medium'"></td>
            </tr>
        </tbody>
ответил Louis Rebolloso 10 PM000000100000003631 2015, 22:54:36
0

Фильтр может быть объектом JavaScript с полями, и вы можете иметь выражение как:

ng-repeat= 'item in list | filter :{property:value}'
ответил Gholamreza Fathpour 14 J000000Thursday16 2016, 09:14:21
0

Возможно, я очень опоздал, но это то, что я в итоге сделал. Я сделал очень общий фильтр.

angular.module('app.filters').filter('fieldFilter', function() {
        return function(input, clause, fields) {
            var out = [];
            if (clause && clause.query && clause.query.length > 0) {
                clause.query = String(clause.query).toLowerCase();
                angular.forEach(input, function(cp) {
                    for (var i = 0; i < fields.length; i++) {
                        var haystack = String(cp[fields[i]]).toLowerCase();
                        if (haystack.indexOf(clause.query) > -1) {
                            out.push(cp);
                            break;
                        }
                    }
                })
            } else {
                angular.forEach(input, function(cp) {
                    out.push(cp);
                })
            }
            return out;
        }

    })

Тогда используйте это так

<tr ng-repeat-start="dvs in devices |  fieldFilter:search:['name','device_id']"></tr>

Ваше окно поиска будет похоже на

<input ng-model="search.query" class="form-control material-text-input" type="text">

где name и device_id - это свойства в dvs

ответил Raj Sharma 16 Maypm18 2018, 13:18:41

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132