Этого можно достичь, используя комбинацию методов map
, filter
и some
Array
.Используйте оператор распространения ...
, чтобы исходный массив не обновлялся в дочерних объектах.
filterIt($event) {
this.filter.RegCategoryName = $event.target.value;
this.dataObject = staticData.filter(value => {
const data = { ...value };
data.List = data.List.map(ch => {
const list = { ...ch };
list.RegistrationCategory = list.RegistrationCategory.filter(gChild => {
return gChild.RegCategoryName.toLowerCase().indexOf(this.filter.RegCategoryName.toLowerCase()) !== -1
});
return list;
});
return data.List.some(list => !!list.RegistrationCategory.length);
});
}
Примечание : избегайте использования имен переменных с заглавной буквой.
Вот рабочий пример для StackBlitz .
Объяснение :
Структура, используемая здесь, довольно сложна, поэтому я полагаю, что я 'начну изнутри.Давайте начнем с самого внутреннего filter
.
list.RegistrationCategory = list.RegistrationCategory.filter(gChild => {
return gChild.RegCategoryName.toLowerCase().indexOf(this.filter.RegCategoryName.toLowerCase()) !== -1
});
Метод filter()
создает новый массив со всеми элементами, которые проходят тест, реализованный предоставленной функцией.
Это должно быть достаточно ясно.Здесь используется то же условие, что и в фильтре Angular Material mat-table
.Это отфильтрует, если RegCategoryName
содержит критерий поиска.Я говорю содержать, потому что это будет соответствовать new Course
, даже если ваш поисковый термин ew
.Если это не то, что вы хотите, вы можете использовать startsWith
вместо этого.Это будет соответствовать, только если ваш поисковый термин new
, а не ew
.
list.RegistrationCategory = list.RegistrationCategory.filter(gChild => {
return gChild.RegCategoryName.toLowerCase().startsWith(this.filter.RegCategoryName.toLowerCase())
});
Переход к первому родительскому массиву List
.Мы не хотим filter
или изменять объекты здесь.Вместо этого мы просто хотим тот же объект, но с новым фильтрованным RegistrationCategory
.Это хорошо подходит для map
, так как map
возвращает массив с таким же количеством объектов (с некоторыми изменениями элементов в объекте, если это необходимо).
map()
метод создает новый массив с результатами вызова предоставленной функции для каждого элемента в вызывающем массиве.
Так что в нашем map
мы будем обновлять RegistrationCategory
используя filter
, который мы создали выше.Мы не можем изменить ch
напрямую, поскольку это приведет к изменению исходного объекта.Таким образом, вместо этого мы будем мелко клонировать ch
, используя синтаксис распространения , в переменную list
, модифицировать RegistrationCategory
в нашей новой переменной list
, используя приведенный выше filter
, и возвращать объект.Теперь это дает нам массив List
как есть, просто обновляя RegistrationCategory
в каждом объекте.
Теперь для финальной части нам нужно от filter
до staticData
.Как и в map
, мы снова будем использовать синтаксис распространения, так как мы не хотим обновлять исходный объект.data.List
теперь будет фильтровать каждый RegistrationCategory
благодаря нашему внутреннему фильтру, поэтому нам просто нужно вернуть значение true
/ false
в зависимости от того, есть ли в массиве List
какой-либо объект, длина которого RegistrationCategory
большечем 0. Мы можем использовать some
для этого.
Метод some()
проверяет, прошел ли хотя бы один элемент в массиве тест, реализованный предоставленной функцией.Он возвращает логическое значение.
Так что если любой RegistrationCategory
в массиве List
имеет длину больше 0 (так как это все, что нас интересует, присутствует ли какой-либо RegistrationCategory
после нашегосамый внутренний фильтр отфильтровал List
), он возвращает true
и добавляется к отфильтрованному dataObject
.
Таким образом, мы получаем каждый объект в staticData
, чей массив List
содержит объект, где RegistrationCategory
имеет некоторые данные.
Надеюсь, это прояснит, почему у вас возникли проблемы с вашим кодом и почему вы не можете использовать фильтр для всех трех массивов.