Подключение динамически генерируемого поля ввода к mat-autocomplete

Я разрешаю пользователям динамически создавать поля ввода. Для каждого из этих полей ввода я хочу подключить его к отдельному мат-автозаполнению, чтобы они работали независимо друг от друга. Я столкнулся с кирпичной стеной, потому что не могу динамически создать ссылку на элемент (#auto здесь), которая соединяет автозаполнение с вводом. Как мне этого добиться?

<div
  class="row"
  *ngFor="let field of getControls('requestFields'); let i = index"
  formArrayName="requestFields"
>
  <ng-container [formGroupName]="i">
    <div class="col-md-4">
      <mat-form-field class="example-full-width">
        <input
          type="text"
          placeholder="Name"
          matInput
          formControlName="reqName"
          matAutocomplete="auto"
        />
        <mat-autocomplete #auto="matAutocomplete">
          <mat-option
            *ngFor="let option of (filteredColumns | async)"
            [value]="option"
          >
            {{ option }}
          </mat-option>
        </mat-autocomplete>
      </mat-form-field>
    </div>
    <div class="col-md-2">
      <div class="togglebutton">
        <label>
          <span>Optional</span>
          <input type="checkbox" formControlName="reqOption" />
          <span class="toggle"></span>
        </label>
      </div>
    </div>
    <div class="col-md-4">
      <mat-form-field>
        <input
          matInput
          formControlName="reqValidations"
          placeholder="Validation"
          type="text"
        />
      </mat-form-field>
    </div>
  </ng-container>
</div>

1 ответ

Хорошая вещь о mat-autocomplete является то, что он полностью отделен от mat-form-field поэтому вы можете поместить его в любое место за пределами динамически генерируемых строк. Итак, на вашем примере - решение может выглядеть так:

<div
  class="row"
  *ngFor="let field of getControls('requestFields'); let i = index"
  formArrayName="requestFields"
>
  <ng-container [formGroupName]="i">
    <div class="col-md-4">
      <mat-form-field class="example-full-width">
        <input
          type="text"
          placeholder="Name"
          matInput
          formControlName="reqName"
          matAutocomplete="auto"
        />
      </mat-form-field>
    </div>
   <!-- other dynamic content -->
  </ng-container>
</div>
<mat-autocomplete #auto="matAutocomplete">
  <mat-option *ngFor="let option of filteredColumns | async" [value]="option">
    {{ option }}
  </mat-option>
</mat-autocomplete>

Тогда вы могли бы иметь обработчик событий для keyup на входе, который запускает обновление для filteredColumns

<mat-form-field class="example-full-width">
  <input
    type="text"
    placeholder="Name"
    matInput
    formControlName="reqName"
    matAutocomplete="auto"
    (keyup)="reqNameChanged(field.get('reqName')?.value)"
  />
</mat-form-field>

И в вашем компоненте вы можете настроить filteredColumns наблюдаемый, который запускается субъектом из keyup обработчик события:

import { Component, OnInit } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import {
  debounceTime,
  distinctUntilChanged,
  filter,
  switchMap
} from 'rxjs/operators';

@Component({
  selector: 'example',
  templateUrl: './example.html',
  styleUrls: ['./example.scss']
})
export class ExampleComponent implements OnInit {
  filteredColumns: Observable<string[]>;

  reqNameSubject: Subject<string> = new Subject<string>();

  constructor(private lookup: ILookupService) {}

  ngOnInit() {
    this.filteredColumns = this.reqNameSubject.pipe(
      filter(v => !!v),
      debounceTime(300),
      distinctUntilChanged(),
      switchMap(value =>
        /* call for the autocomplete data */
        this.lookup.search(value)
      )
    );
  }

  reqNameChanged(value: string) {
    this.reqNameSubject.next(value);
  }
}

Я надеюсь, что это помогает.

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