Угловой материал 2 Фильтр DataSource с вложенным объектом

У меня есть угловой проект 4 с материалом 2, я хочу отфильтровать данные в MatTable. Фильтр DataSource работает отлично, когда мы фильтруем данные в поле, которое не является вложенным.

this.dataSource = new MatTableDataSource([
     { orderNumber: 1, orderInfo: { type: 'ABC'}, date: '12/3/2012 9:42:39 AM'},
     { orderNumber: 3, orderInfo: { type: 'Hello' }, date: '12/2/2018 9:42:39 AM'},
]);

Фильтр работает нормально для orderNumber, дата, но не работает должным образом с полем типа в объекте orderInfo.

Ответ 1

DataSource имеет метод filterPredicate(), который необходимо переопределить в нашем приложении следующим образом. Добавьте этот код в свой компонент после инициализации источника данных.

this.dataSource.filterPredicate = (data, filter: string)  => {
  const accumulator = (currentTerm, key) => {
    return key === 'orderInfo' ? currentTerm + data.orderInfo.type : currentTerm + data[key];
  };
  const dataStr = Object.keys(data).reduce(accumulator, '').toLowerCase();
  // Transform the filter by converting it to lowercase and removing whitespace.
  const transformedFilter = filter.trim().toLowerCase();
  return dataStr.indexOf(transformedFilter) !== -1;
};

Ответ 2

Вот решение, которое включает рекурсию, поэтому вам не нужно жестко кодировать каждый вложенный объект или пар их/значение.

this.dataSource.filterPredicate = (data, filter: string)  => {
  const accumulator = (currentTerm, key) => {
    return this.nestedFilterCheck(currentTerm, data, key);
  };
  const dataStr = Object.keys(data).reduce(accumulator, '').toLowerCase();
  // Transform the filter by converting it to lowercase and removing whitespace.
  const transformedFilter = filter.trim().toLowerCase();
  return dataStr.indexOf(transformedFilter) !== -1;
};

И nestedFilterCheck

  nestedFilterCheck(search, data, key) {
    if (typeof data[key] === 'object') {
      for (const k in data[key]) {
        if (data[key][k] !== null) {
          search = this.nestedFilterCheck(search, data[key], k);
        }
      }
    } else {
      search += data[key];
    }
    return search;
  }

Спасибо @Sagar Kharche за filterPredicate.

Ответ 3

Это очень общее решение и будет работать точно. Это не зависит от структуры JSON, будь то простой или вложенный, это решение работает для всех.

this.dataSource.filterPredicate = (data: any, filter) => { const dataStr =JSON.stringify(data).toLowerCase(); return dataStr.indexOf(filter) != -1; }