Применяйте динамические фильтры с помощью тегов

У меня есть список элементов, который отображается в таблице с помощью ng-repeat. Я хочу применить динамические фильтры, которые добавляются с помощью тегов (ng-tags-input). Этот ввод тега генерирует динамические теги, которые я хочу использовать в качестве фильтров.

Вот созданный мной кусок. Как я могу использовать записи из этих тегов для создания фильтров.

Для одного элемента я попробовал

<body ng-controller="MainCtrl">
    <tags-input ng-model="tags"></tags-input>
    <p>Model: {{tags}}</p>
    <table border=1 cellpadding=10px>
        <tr ng-repeat = "t in tableData | filter:tags[0].text">
            <td>{{t.data1}}</td>
            <td>{{t.data2}}</td>
        </tr>
    </table>
</body>

но для этого потребуется только один элемент. Я хочу применить в качестве фильтра целые записи tags.

Я видел другие вопросы по SO, но у них есть фильтры, применяемые как

<tr ng-repeat = "t in tableData | filter:{data1:someFilteData}">

Вот одна из скрипки. Я не могу применить фильтр из массива JSON. Как я могу это сделать?


person Aniket Sinha    schedule 21.05.2014    source источник
comment
Приведите пример возможного ввода и желаемого вывода.   -  person gkalpak    schedule 22.05.2014
comment
См. Этот plnkr.co/edit/MiMT4T1Fdkcx9xRhi1ub?p=preview. Здесь я хочу использовать теги для получения данных фильтра, так как я хочу применить несколько фильтров. Затем я хочу передать теги как фильтры. Возможный ввод: data1, data3 (как теги) Возможный вывод: данные таблицы, отфильтрованные через data1 и data3   -  person Aniket Sinha    schedule 22.05.2014
comment
Да, но что означает фильтрация через data1 и data3? Что нужно вернуть? Элементы, у которых есть ключ, соответствующий dat1 или data3? Элементы, у которых есть ключи для соответствия как data1, так и data3? Сравнивать со значениями вместо ключей? Что нужно вернуть в вашем примере скрипки?   -  person gkalpak    schedule 22.05.2014


Ответы (1)


Если вы хотите включить элементы, значение свойства которых соответствует хотя бы одному из тегов, вы можете определить свой собственный фильтр следующим образом:

app.filter('filterByTags', function () {
    return function (items, tags) {
        var filtered = []; // Put here only items that match
        (items || []).forEach(function (item) { // Check each item
            var matches = tags.some(function (tag) {          // If there is some tag
                return (item.data1.indexOf(tag.text) > -1) || // that is a substring
                       (item.data2.indexOf(tag.text) > -1);   // of any property's value
            });                                               // we have a match
            if (matches) {           // If it matches
                filtered.push(item); // put it into the `filtered` array
            }
        });
        return filtered; // Return the array with items that match any tag
    };
});

И использовать это так:

<tr ng-repeat="t in tableData | filterByTags:tags">

См. Также эту короткую демонстрацию.

person gkalpak    schedule 22.05.2014
comment
Это то, что я искал. Я думал, что это можно сделать с помощью встроенных фильтров, не создавая собственный фильтр самостоятельно. В любом случае, большое спасибо за вашу помощь. - person Aniket Sinha; 22.05.2014
comment
Если я удалю все теги, в таблице не будет вообще никаких элементов. Какие изменения следует внести, чтобы при отсутствии тега в таблице отображались все записи? У меня есть этот Plunker по адресу plnkr.co/edit/3MLi92cuRkw96xz644Zg?p=preview. Можете ли вы проверить, правильный ли это способ сделать? Кроме того, в вашем коде (items || []).forEach(function (item) { // Check each item я не понимаю причину, по которой вы использовали items || [], элементы в любом случае никогда не являются пустым массивом. Вы можете это объяснить. Заранее спасибо. - person Aniket Sinha; 26.05.2014
comment
Ваша реализация верна - одно замечание: лучше поставить галочку в верхней части функции (if (tags.length === 0) { return items; }), чтобы избежать ненужных вычислений. - person gkalpak; 26.05.2014
comment
Что касается вашего другого вопроса, (items || []) является защитой на случай, если нашему фильтру передается undefined аргумент (например, если данные были получены из серверной части, а вы забыли инициализировать tableData пустым массивом (до тех пор, пока не будут получены фактические данные), наш отфильтрованный будет попробуйте вызвать forEach на undefined, и вы получите сообщение об ошибке в консоли. (items || []) означает: используйте items, если он не является ложным (например, undefined, null, false, '', 0); затем используйте []). Надеюсь, это имеет смысл. - person gkalpak; 26.05.2014
comment
Спасибо за быстрый ответ. И да, теперь это имеет больше смысла. - person Aniket Sinha; 26.05.2014
comment
Еще одна вещь, как сделать его нечувствительным к регистру? Преобразовать оба параметра в нижний регистр, а затем сопоставить? Можете ли вы изменить существующий Plunk, чтобы сделать именно это, поскольку я не знаю, где использовать angular.lowercase - person Aniket Sinha; 26.05.2014
comment
Посмотрите этот Plunk plnkr.co/edit/U5K4tgla0JCRlwbUY3vB?p=preview. правильный путь? - person Aniket Sinha; 26.05.2014
comment
Да, это правильно. Вот альтернативная реализация, которая могла бы быть более эффективной: plnkr.co/edit/63kKR9cyvyxWogyP4GB5?p=preview (но если ваша таблица не огромна, вы не увидите заметной разницы в производительности) - person gkalpak; 26.05.2014