Динамическая сетка фильтра трубы - PullRequest
0 голосов
/ 21 декабря 2018

У меня есть общая сетка, как показано ниже

<table class="table">
    <thead>
        <tr role="row" class="headers-filters">
            <th *ngFor="let objGColumn of gridColumns; let idx=index;">
                <dt-column-header [(filter)]="grdFilters[objGColumn.propertyKey]"></dt-column-header>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr role="row" *ngFor="let objRC of recordList | filterColumn: grdFilters; let idx=index;">
            <td class="text-center" *ngFor="let objGColumn of gridColumns; let idx=index;">           
                <span [textContent]="objRC[objGColumn.propertyKey]"></span>
            </td>
        </tr>
    </tbody>
</table>

Где gridColumns будет массивом отображаемых столбцов.

dt-column-header - это компонент, который будет содержать текстовое поле для столбца поиска.У него есть фильтр свойств двустороннего связывания, который будет фильтровать в сетке

Фильтры будут выглядеть как grdFilters = {LastName: "123", FirstName: "456"}

Моя труба похожа на приведенную ниже.Я взял ссылку из https://www.code -sample.com / 2018/07 / angular-6-search-filter-pipe-table-by.html

@Pipe({
  name: 'filterColumn'
})
export class GrdFilterPipe implements PipeTransform {
  transform(items: any, filter: any, defaultFilter: boolean): any {
    if (!filter){
      return items;
    }

    if (!Array.isArray(items)){
      return items;
    }

    if (filter && Array.isArray(items)) {
      let filterKeys = Object.keys(filter);

      if (defaultFilter) {
        return items.filter(item =>
            filterKeys.reduce((x, keyName) =>
                (x && new RegExp(filter[keyName], 'gi').test(item[keyName])) || filter[keyName] == "", true));
      }
      else {
        return items.filter(item => {
          return filterKeys.some((keyName) => {
            return new RegExp(filter[keyName], 'gi').test(item[keyName]) || filter[keyName] == "";
          });
        });
      }
    }
  }
}

Мой первый выпускЭто труба не вызывает, когда изменяется gridFilters.Мне пришлось сделать это нечистым , что повлияет на производительность.

Другая проблема заключается в том, что труба работает нормально с {LastName: "123"} ИЛИ {FirstName: "456"}

Но нетработа с {LastName: "123", FirstName: "456"} ИЛИ {LastName: "", FirstName: "456"} ИЛИ {LastName: "123", FirstName: ""}

1 Ответ

0 голосов
/ 26 декабря 2018

Быстрый ответ:

«Моя первая проблема заключается в том, что канал не вызывает при изменении gridFilters»:

РЕКОМЕНДУЕТСЯ: Оставьте свой канал какчистый канал и переназначить gridFilters вместо его изменения.Другими словами, вместо использования ngModel в вашем dt-column-header компоненте, используйте входное событие и переназначьте переменную gridFilters.

ИЛИ (НЕ РЕКОМЕНДУЕТСЯ): Сделайте вашу трубу нечистый канал , добавив pure: false в декоратор @Pipe:

@Pipe({
  name: 'searchFilter',
  pure: false
})

См. StackBlitz DEMO с рабочим примером кода.

«Другая проблема заключается в том, что труба работает нормально с ... но не работает с ней»:

Проблема с кодом трубы:

return items.filter(item => {
  return filterKeys.some((keyName) => {
    return new RegExp(filter[keyName], 'gi').test(item[keyName]) || filter[keyName] == "";
  });
});

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

Подробный ответ

объяснение чистых / нечистых труб:

Ваша труба pure pipe (тип канала по умолчанию, когда метаданные не используются pure: false в @Pipe decorator).Чистый канал будет выполняться только в случае изменения примитивного входного значения (String, Number, Boolean, Symbol) или изменения ссылки на объект (Date, Array, Function, Object).

Angular Docs - Чистые трубы

Таким образом, у вас есть 2 варианта решения:

Решение 1 (рекомендуется) :

В заказечтобы ваш канал снова вызывался при изменении gridFilters, вам нужно переназначить его вместо его изменения .Другими словами, вместо использования ngModel в компоненте dt-column-header используйте событие ввода и переназначьте переменную gridFilters.

Решение 2 (не рекомендуется) :

Сделайте вашу трубу нечистой трубкой , добавив pure: false в @Pipe декораторе:

@Pipe({
  name: 'searchFilter',
  pure: false
})

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

Angular Docs - нечистые каналы говорит:

Имея это в виду, с большой осторожностью используйте нечистую трубу.Дорогая, долго работающая труба может испортить впечатление пользователя.

...