Двухстороннее связывание Angular 7: канал, принимающий массив в качестве аргумента, не работает должным образом - PullRequest
0 голосов
/ 29 марта 2019

Я написал канал Angular 7, который принимает 2 аргумента: массив для фильтрации и массив совпадающих фильтров.

import { Pipe, PipeTransform } from '@angular/core';

import { Order } from '../models';

@Pipe({
  name: 'filterOrdersByDate'
})
export class CapacityOrderPipe implements PipeTransform {

  transform(orders: Order[], periods: string[]): Order[] {

    if (!orders) return [];
    if (!periods.length) return orders;

    return orders.filter(function(order: Order) {

      for (var i=0; i<periods.length; i++) if (order.crossId.indexOf(periods[i])>-1) return true;
      return false;

    });

  }

}

orders - это массив заказов, как определено в модели Order.Каждый заказ имеет свойство crossId.Это массив строк, представляющих начальную дату.

В моем component.ts у меня есть этот метод для добавления / удаления даты из массива периодов:

toggleOrder(date: string) {
  let i = this.filters.orders.indexOf(date);
  (i<0)? this.filters.orders.push(date) : this.filters.orders.splice(i, 1);
}

, и этововлеченный component.html код:

<mat-list class="list">
  <mat-list-item *ngFor="let o of (data.orders | filterOrdersByDate : filters.orders)">
    <mat-divider></mat-divider>
    <h3 mat-line>Order: {{o.group}}-{{o.number}}</h3>
    ...
   </mat-list-item>
</mat-list>

...

<div *ngFor="let f of filters">
<mat-checkbox color="primary" [indeterminate]="false" (change)="toggleOrder(f.date)">{{f.date}}</mat-checkbox>
</div>

Когда я устанавливаю флажок в component.html, метод toggleOrder () добавляет или удаляет дату в массиве фильтров.Итак, я ожидаю, что канал будет фильтровать массив data.orders.К сожалению, это не работает.Я потратил 2 часа на поиск решения и обнаружил, что, если я передам длину массива фильтров в канал, все будет работать, как и ожидалось.Таким образом, похоже, что Angular устанавливает двустороннюю привязку к длине массива фильтров, но не к самому массиву фильтров.

Как это работает?Я ожидаю, что Angular устанавливает двустороннюю привязку ко всем свойствам, определенным в классе компонента: строках, массивах, числах и т. Д. Но канал не прослушивает изменения содержимого массива.Только если я передам длину массива в трубу, это сработает.Но если у меня есть канал, который принимает строку для фильтрации данных вместо массива, он отлично работает.

1 Ответ

0 голосов
/ 29 марта 2019

Если вы посмотрите на Angular Docs , он говорит о таких сценариях, как эти. Это препятствует работе труб, работающих на массивах, из-за их низкой производительности.

То, что вы пытаетесь достичь, одним из двух способов.

Вы можете обновить свою трубу, чтобы она стала «нечистой»:

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

Или вы можете сохранить его как чистый канал и позволить Angular отслеживать ваши изменения, используя встроенное обнаружение изменений, каждый раз переназначая значение массива.

toggleOrder(date: string) {
  let i = this.filters.orders.indexOf(date);
  (i<0)? this.filters.orders.push(date) : this.filters.orders.splice(i, 1);
  this.filters.orders = this.filters.orders.slice(0);
}

Как указывалось вначале, хотя, это не самый оптимальный способ выполнить эту задачу. Я придерживаюсь рекомендаций Angular и перенесу этот канал в метод, который можно вызвать из вашего toggleOrder метода.

Команда Angular и многие опытные разработчики Angular сильно рекомендуем перенести логику фильтрации и сортировки в компонент сам. Компонент может выставлять фильтрованные герои или отсортированные герои собственности и взять под контроль, когда и как часто выполнять поддерживающая логика Любые возможности, которые вы бы положили в трубу и общий доступ к приложению может быть написано в фильтрации / сортировке сервис и вводится в компонент.

...