Как я могу использовать несколько экземпляров ngx-mat-select-search без проверки длины входного массива?

Я создал многоразовый компонент ngx-mat-select-search, который выглядит так

mat-tooltip-select-all.comComponent.ts

export class MatTooltipSelectAllComponent implements OnInit, AfterViewInit, OnDestroy {

  @Input() placeHolderName: string;

  @Input() isDate: boolean = false;

  /** emit an event when a new option is selected */
  @Output() newOptionSelected = new EventEmitter<SelectOption[]>();

  /** control for the selected option for multi-selection */
  public multiCtrl: FormControl<SelectOption[]> = new FormControl<SelectOption[]>([]);

  /** control for the MatSelect filter keyword multi-selection */
  public multiFilterCtrl: FormControl<string> = new FormControl<string>('');

  /** list of selectOptions filtered by search keyword */
  public filteredMulti: ReplaySubject<SelectOption[]> = new ReplaySubject<SelectOption[]>(1);

  public tooltipMessage = 'Select All / Unselect All';

  @ViewChild('multiSelect', { static: true }) multiSelect: MatSelect;

  /** Subject that emits when the component has been destroyed. */
  protected _onDestroy = new Subject<void>();

  @Input() set selectOptions(selectOptions: SelectOption[]) {
    this._selectOptions = selectOptions;
    // load the initial option list
    this.filteredMulti.next(this.selectOptions.slice());
  }
  get selectOptions(): SelectOption[] {
    return this._selectOptions;
  }

  private _selectOptions: SelectOption[];

  constructor() { }

  ngOnInit() {
    // set initial selection to all
    // this.multiCtrl.setValue(this._selectOptions.slice());

    // listen for select option value changes
    this.multiCtrl.valueChanges
      .pipe(takeUntil(this._onDestroy))
      .subscribe(() => {
        this.newOptionSelected.emit(this.multiCtrl.value);
      });    

    // listen for search field value changes
    this.multiFilterCtrl.valueChanges
      .pipe(takeUntil(this._onDestroy))
      .subscribe(() => {
        this.filterMulti();
      });
  }

Я использую его несколько раз для родительского компонента, но по какой-то причине данные загружаются только в первом экземпляре ngx-mat-select-search. Например

               //pdoNames is loaded
                <app-mat-tooltip-select-all
                  #pdoNameFilter
                  class = "col-md-6"
                  (newOptionSelected) = "handleFilter($event, Filter.PDOName)"
                  [selectOptions] = "pdoNames"
                  placeHolderName = "PDO Name"
                ></app-mat-tooltip-select-all>
                //beneficiaryClassifications is not loaded/filtered list  is empty
                <app-mat-tooltip-select-all
                  #beneficiaryFilter
                  class = "col-md-6"
                  (newOptionSelected) = "handleFilter($event, Filter.BeneficiaryClassification)"
                  [selectOptions] = "beneficiaryClassifications"
                  placeHolderName = "Beneficiary Classification"
                ></app-mat-tooltip-select-all>

Данные извлекаются в родительском компоненте следующим образом

родительский компонент ts

  ngOnInit(): void {
    this.reportService
      .getFundingNeedsSummary()
      .pipe(take(1))
      .subscribe((response: any) => {
      // sets pdoNames and beneficiaryClassifications here
      });
  }

Мне нужно проверить длину параметра, например *ngIf="beneficiaryClassifications?.length > 0" в последующих экземплярах, чтобы он работал. Но проблема этого подхода в том, что компонент не будет отображаться, если длина параметра пуста или равна 0.

Как я могу заставить это работать без проверки длины параметра или заставить компонент отображаться, даже если длина параметра равна 0? Я пробовал использовать *ngIf = "beneficiaryClassifications?.length == 0 || beneficiaryClassifications?.length > 0", но он не загружает данные/параметры фильтра становятся пустыми.

Полный воспроизводимый код: https://stackblitz.com/edit/github-qartsv?file=src%2Fapp%2Fapp.comComponent.html

пожалуйста, поделитесь полным воспроизводимым кодом, если возможно, стекблицом, где возникает проблема!

Naren Murali 03.06.2024 10:06

@NarenMurali добавил ссылку на Stackblitz, извините за задержку, мне потребовалось некоторое время, чтобы настроить и воспроизвести код в stackblitz.

lance2k 03.06.2024 13:51
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
2
2
97
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Попробуйте использовать OnChanges, чтобы обнаружить изменения в дочернем компоненте.

https://angular.io/api/core/OnChanges

Также попробуйте установить ng-модель с двусторонней привязкой, чтобы убедиться, что вы получаете каждое изменение данных.

https://angular.dev/api/forms/NgModel и https://dev.to/tonyhicks20/angular-two-way-binding-between-parent-and-child-comComponents-16kl

Я не думаю, что мне нужна двусторонняя привязка данных. Единственная цель дочернего компонента app-mat-tooltip-select-all — получить список selectOptions от родительского компонента и вернуть выбранные параметры в (newOptionSelected) = "handleFilter($event, Filter.BeneficiaryClassification)".

lance2k 31.05.2024 08:39
Ответ принят как подходящий

Нам нужно обновить ссылку на массив, когда мы выполняем операцию push, поскольку содержимое изменяется, но местоположение памяти остается прежним.

Angular считает, что ничего не изменилось, поэтому вы не можете просмотреть список, только выполняя операцию push.

Когда мы выполняем деструктуризацию массива (this.clientType = [...this.clientType]), у массива появляется новая ссылка на память, поэтому angular запускает обнаружение изменений по @Input и делает список видимым.

populateFilters() {
    this.tableData.forEach((pdo) => {
      const clientType = {
        id: pdo?.client_type ? pdo?.client_type.id : 'null',
        name: pdo?.client_type ? pdo?.client_type.name : 'null',
      };
      if (!this.isExisting(clientType, this.clientType)) {
        this.clientType.push(clientType);
      }
    });
    this.clientType = [...this.clientType]; // <- changed here!
  }

Демо-версия Stackblitz

Я заметил, что фильтры, заполненные с помощью Array.push(), не заполняются. Но я не знал почему, спасибо за объяснение.

lance2k 03.06.2024 14:07

Другие вопросы по теме