Angular 9: более одного ngb-типа в одной форме? - PullRequest
0 голосов
/ 20 апреля 2020

Я использую компонент NgbTypeahead из NG-Boostrap 6.0.3 в моем приложении Angular 9. Первый работает нормально, но в моей форме их довольно много.

Нужно ли добавлять отдельный ViewChild и отдельную функцию поиска для каждого из них? Или я что-то упустил? Может кто-нибудь указать мне пример с более чем одним?

Для справки, вот Stackblitz только с одним.

1 Ответ

0 голосов
/ 21 апреля 2020

ну, на самом деле мой комментарий НЕ верен, представьте, что у вас есть 2 ngbTypeHead. Вам нужно, чтобы фокус $ и щелкните $ был массивом, для этого вы можете использовать карту, например,

focus$ = [0,1].map(_=>new Subject<string>());
click$ = [0,1].map(_=>new Subject<string>());

Ну, Вы также можете сделать что-то вроде (я использую массив и карту дурака), но это то же самое, что:

focus$ = [new Subject<string>(),new Subject<string>()];

Я использую массив для модели

model: any[]=[];

И изменить функция поиска, которая получила в качестве параметров: индекс, экземпляр и термин (индекс необходим для ссылки на субъекты

searchType(index,instance, text$) {
    return (text$: Observable<string>) => {
      const debouncedText$ = text$.pipe(
        debounceTime(200),
        distinctUntilChanged()
      );
      const clicksWithClosedPopup$ = this.click$[index].pipe(
        filter(() => !instance.isPopupOpen())
      );
      const inputFocus$ = this.focus$[index];

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

Затем единственное, что нам нужно, это изменить наш ngbTypeahead

  <input
        ...
  [(ngModel)]="model[index]"
  [ngbTypeahead]="searchType(i,instance,$text)"
  (focus)="focus$[i].next($any($event).target.value)"
  (click)="click$[i].next($any($event).target.value)"
  #instance="ngbTypeahead"
  >

Вы можете увидеть пример в stackblitz

Обновление Если нам нужны разностные данные, мы можем улучшить функцию поиска, передавая «данные», поэтому если мы добавим новый параметр для поиска:

searchType(index,instance, data,text$) { //<--pass "data"
    return (text$: Observable<string>) => {
      const debouncedText$ = text$.pipe(
        debounceTime(200),
        distinctUntilChanged()
      );
      const clicksWithClosedPopup$ = this.click$[index].pipe(
        filter(() => !instance.isPopupOpen())
      );
      const inputFocus$ = this.focus$[index];

      return merge(debouncedText$, inputFocus$, clicksWithClosedPopup$).pipe(
        map(term =>
          (term === ""
            ? data          //<--here use data
            : data.filter(  //<--here use data too
                v => v.toLowerCase().indexOf(term.toLowerCase()) > -1
              )
          ).slice(0, 10)
        )
      );
    };
  }

Мы можем изменить вызов и написать:

[ngbTypeahead]="searchType(i,instance,states,$text)"

Другой вариант, согласно поиску "index" в том или ином массив, так что функция становится как

searchType(index,instance, text$) { 
    const data=index==0?states:this.fruits; //<--the data according the index
    return (text$: Observable<string>) => {
      const debouncedText$ = text$.pipe(
        debounceTime(200),
        distinctUntilChanged()
      );
      const clicksWithClosedPopup$ = this.click$[index].pipe(
        filter(() => !instance.isPopupOpen())
      );
      const inputFocus$ = this.focus$[index];

      return merge(debouncedText$, inputFocus$, clicksWithClosedPopup$).pipe(
        map(term =>
          (term === ""
            ? data          //<--here use data
            : data.filter(  //<--here use data too
                v => v.toLowerCase().indexOf(term.toLowerCase()) > -1
              )
          ).slice(0, 10)
        )
      );
    };
  }
...