Динамический Типоголовый Угловой

#angular #typehead

Вопрос:

Я хочу создать форму, в которой вводимые заголовки будут добавляться динамически. Заголовок типа содержит типы контактов. Для каждой записи я хочу вывести свой собственный тип контакта. Количество полей ввода может быть определено пользователем. Как все это может быть реализовано с помощью компонента typeahead? Если у меня в форме несколько заголовков, при нажатии на них открывается окно поиска всех заголовков. В настоящее время это выглядит так:

 <div formArrayName="contacts">
  <div *ngFor="let contact of customerForm.get('contacts')['controls']; let i = index">
    <div formGroupName="{{ i }}">
      <div class="mb-2">
        <div class="row">
          <div>
            <input type="hidden" id="contactId" formControlName="id">
          </div>
          <div class="col-6">
            <label for="name">{{ 'customereditcomponent.label_ContactValue' | translate }}</label>
            <input type="text" class="form-control" id="contactValue" formControlName="value">
          </div>
          <div class="col-5">
            <div>
              <ng-template #contactTypeTemplate let-contactType="result">
                <div *ngIf="contactType.description != null">{{contactType.description}}</div>
              </ng-template>

              <label for="contactType{{i}}">{{ 'customereditcomponent.label_ContactType' | translate }}</label>
              <div class="input-group">
                <input id="contactType{{i}}" type="text" class="form-control" [ngbTypeahead]="searchContactTyppe" (focus)="focusContactType$.next($any($event).target.value)" (click)="clickContactType$.next($any($event).target.value)" [inputFormatter]="ContactTypeFormatter" [resultTemplate]="contactTypeTemplate" (selectItem)="selectedContactType($event)" #instanceContactType="ngbTypeahead" />
                <div class="input-group-append">
                  <span class="input-group-text"><i class="feather icon-search"></i></span>
                </div>
              </div>
            </div>
          </div>
          <div *ngIf="selectedCustomer == null " class="col-1">
            <button type="button" class="btn btn-link" (click)="deleteContact(i)"><i class="fas fa-times"></i></button>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
 

Контакты могут быть добавлены пользователем динамически.

 import '...'

@Component({
  selector: 'app-customer-edit',
  templateUrl: './customer-edit.component.html',
  styleUrls: ['./customer-edit.component.scss']
})
export class CustomerEditComponent implements OnInit {
  customerForm: FormGroup;

  contactTypes;
  contactType: ContactType;
  @ViewChild('instanceContactType') instanceContactType: NgbTypeahead;
  focusContactType$ = new Subject<string>();
  clickContactType$ = new Subject<string>();

  constructor() { }

  ngOnInit(): void {
    this.customerForm = new FormGroup( {
      id: new FormControl(),
      externalId: new FormControl(),
      isCompany: new FormControl(),
      mainAddress: new FormGroup({
        firstName: new FormControl(),
        name: new FormControl(),
        companyName: new FormControl(),
        street: new FormControl(),
        zipcode: new FormControl(),
        city: new FormControl()
      }),
      customerAddresses: new FormArray([]),
      contacts: new FormArray([]),
      contactPersons: new FormArray([])
    });

    this.loadContactTypes();
  }

  selectNewContactType(contactType: ContactType): void {
    this.loadContactTypes();
    this.contactType = contactType;
    this.instanceContactType.writeValue(contactType);
  }

  loadContactTypes(): void {
    this.contactTypes = [];
    this.contactTypes = this.contactTypes.concat(
      new ContactType('-1', 'Neuer Kontakttyp'));
    this.contactTypes = this.contactTypes.concat(this.basicDataService.getContactTypes());
  }

  selectedContactType(item): void{
    const contactType: ContactType = item.item;
    if (contactType.id === '-1' ) {
      this.openModalDialog(this.createNewContactType);
    } else {
      this.contactType = item.item;
    }
  }

  searchContactTyppe: OperatorFunction<string, readonly string[]> = (text$: Observable<string>) => {
    const debouncedText$ = text$.pipe(debounceTime(200), distinctUntilChanged());
    const clicksWithClosedPopup$ = this.clickContactType$.pipe(filter(() => !this.instanceContactType.isPopupOpen()));
    const inputFocus$ = this.focusContactType$;

    return merge(debouncedText$, inputFocus$, clicksWithClosedPopup$).pipe(
      map(term => (term === '' ? this.contactTypes
        : this.contactTypes.filter(v => v.description?.toLowerCase().indexOf(term.toLowerCase()) > -1)).slice(0, 10))
    );
  }

  ContactTypeFormatter = (x: ContactType) => x.description;
}

 

Is it possible to use the Typehead in for something like this? If not, are there any alternatives?