2016-09-07 6 views
5

У меня есть несколько фильтров, работающих нормально над ng-repeat. Тем не менее, код кажется излишне длинным для фактического действия фильтров на наборе, и мне интересно, есть ли лучший способ.Каков наилучший способ реализации нескольких фильтров AngularJS?

Вот пример фильтра - этот бит, я в порядке с (если кто не имеет никаких советов) - все они имеют сходную структуру:

app.js

.filter('taskClient', function() { 
    return function (items, clientId) { 
     if (!clientId) { return items; } 
     var filtered = []; 
     angular.forEach(items, function(item) { 
      if (item.client) { 
       if (item.client.id === clientId) { 
        filtered.push(item); 
       } 
      } 
     }); 
     return filtered; 
    } 
}) 

И, как Я сказал - их несколько. Затем, на мой нг-повторе, я реализую их так (это бит, который, кажется, трудно поддерживать и слишком долго, и был бы признателен за информацию о любых лучших методов):

задачи-index.html

<md-list-item icp-task-line ng-repeat="task in TasksCtrl.tasks | taskOwner: TasksCtrl.selectedUserFilter | taskClient: TasksCtrl.clientId | taskDepartment: TasksCtrl.departmentId | taskPriority: TasksCtrl.priority | taskWithClient: TasksCtrl.withClient | taskEndDate: TasksCtrl.endDate | filter: {progress: 0} | filter: searchText | orderBy: TasksCtrl.orderTasks" class="md-2-line"></md-list-item> 

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

Есть ли лучший способ реализовать эти фильтры?

Я также обеспокоен тем, что после прочтения this article Я не понимаю разницу между фильтрами состояния и нестатистическими - это вышеперечисленные фильтры, оптимизированные для производительности?

+0

Хорошо, можете ли вы сказать нам, что у вас есть такой фильтр? То, что на самом деле пытается достичь в процессе отображения. Если будет продемонстрирована демонстрационная демонстрация, это было бы здорово. –

+0

Краткое описание заключалось в том, чтобы иметь возможность фильтровать задачи по всем вышеперечисленным параметрам - вот почему они там. Однако при загрузке применяется только одна - остальные все через ng-модели используют флажки или выпадающие списки. – DJC

+0

Проблема с использованием большого количества фильтров. Это связано с добавлением всех фильтров часов. Чем больше фильтров вы будете трубить, тем больше часов у вас будет, что приведет к снижению производительности. Я предлагаю вам либо реализовать единственный фильтр, который выполняет все тесты, либо один фильтр, который использует многочисленные методы заводских фильтров (удерживайте их в массиве, а в фильтре используйте «forEach»). Существует много шаблонов дизайна, которые вы можете использовать для этого. Важно следить за тем, чтобы количество скошенных фильтров было минимальным. – eitanfar

ответ

0

Я предлагаю вам использовать функцию яваскрипт filter(), который является действительно мощным:

.filter('taskClient', function() { 
    return function(items, clientId) { 
    if (!clientId) { return items; } 
    return items.filter(function(item) { 
     return item.client && item.client.id === clientId; 
    }); 
    } 
}) 
+1

Кроме того, что вырезать пару строк (оцените информацию!) - это не меняет способ применения фильтров - это делает то, что делает мой текущий код – DJC

+1

Нет, это действительно так: сравните 'forEach' и 'filter' docs ... Или попробуйте запустить две реализации на довольно больших массивах и увидите разницу в производительности: она будет огромной ... :-) – MarcoS

+0

Отлично - я обязательно это сделаю, и, как я уже сказал, я ценю информацию там - хорошо знать. См. Вопрос редактирования, хотя, надеюсь, я сделал это немного яснее - это фактическое применение этих фильтров - в html ng-repeat, который кажется сверху, и мне интересно, есть ли лучший способ? – DJC

3

вы можете объединить все подобные фильтры в один, например (я сделал очень приблизительные предположения о структуре вашей задачи модель :), я вставил filter: {progress: 0} фильтр внутри, а):

.filter('taskFilter', function() { 
    return function (items, args) { 
    return items.filter(function(item) { 
     return (!args.selectedUserFilter || item.selectedUserFilter === args.selectedUserFilter) && 
      (!args.clientId || item.client && item.client.id === args.clientId) && 
      (!args.departmentId || item.department && item.department.id === args.departmentId) && 
      (!args.priority || item.priority === args.priority) && 
      (!args.withClient || item.withClient === args.withClient) && 
      (!args.endDate || item.endDate === args.endDate) && 
      item.progress === 0; 
    }); 
    } 
}) 

Теперь HTML может выглядеть

<md-list-item icp-task-line ng-repeat="task in TasksCtrl.tasks | taskFilter: TasksCtrl | filter: searchText | orderBy: TasksCtrl.orderTasks" class="md-2-line"></md-list-item> 
+0

Будет ли это улучшать производительность/уменьшать наблюдателей? И будут ли они работать вместе? – DJC

+0

1. цепочки фильтров в HTML означает, что вывод одного фильтра поступает на вход следующего фильтра, каждый фильтр итерации по полученному массиву заново, объединенный фильтр будет проходить только один раз. 2. каждый фильтр регистрирует часы, комбинированный фильтр регистрирует один вахту. 3. комбинированный фильтр может работать вместе с другими фильтрами, и его результат точно такой же, как и в цепочках в HTML-фильтрах. плункер с обоими фильтрами - http://plnkr.co/edit/2XUlpSz702kqcjFXsMG1?p=preview – Andriy

+0

Извинения за задержку - я просто пришел, чтобы просмотреть ответы, и это, кажется, лучший ответ. Только вопрос, который у меня есть, заключается в том, что удаленные мои текущие связанные фильтры, похоже, не уменьшают количество наблюдателей - это ожидалось? Есть ли еще одна полезность для вашего подхода? – DJC

3

У меня есть два совета для вас. Во-первых, если вы хотите получить отфильтрованный результат в переменной, поэтому вам не нужно снова применять все фильтры для получения счета, вы можете добавить as filtered_result в конце ваших фильтров и перед любым track by..., как описано в documentation.

Другим вашим советом является не принудительное использование фильтров в HTML. Это может быть лучше в вашем случае, чтобы создать функцию, которая фильтрует ваш TasksCtrl.tasksодин раз и сохраняет результаты до свойства TasksCtrl.filteredTasks, которое ваш ng-repeat может повторить с меньшим количеством часов. Если вы хотите сохранить код фильтрации в Угловых фильтрах, вы можете ввести $filter и запустить их вручную в своей функции.

function filterTasks(){ 
    var tasks = TasksCtrl.tasks; 
    tasks = $filter('taskOwner')(tasks, TasksCtrl.selectedUserFilter); 
    tasks = $filter('taskClient')(tasks, TasksCtrl.clientId); 
    tasks = $filter('taskDepartment')(tasks, TasksCtrl.departmentId) 
    tasks = $filter('taskPriority')(tasks, TasksCtrl.priority); 
    tasks = $filter('taskWithClient')(tasks, TasksCtrl.withClient); 
    tasks = $filter('taskEndDate')(tasks, TasksCtrl.endDate) 
    tasks = $filter('filter')(tasks, {progress: 0}); 
    tasks = $filter('filter')(tasks, searchText); 
    tasks = $filter('orderBy')(tasks, TasksCtrl.orderTasks); 
    TasksCtrl.filteredTasks = tasks; 
} 
Смежные вопросы