Добавить выбранные элементы в ng-select с несколькими и typeahead - PullRequest
0 голосов
/ 09 ноября 2018

Я использую ng-select , чтобы выбрать несколько значений из большого списка, который загружается удаленно, в зависимости от того, что пользователь вводит в поле. Вот мои требования:

  1. Метки добавляются динамически
  2. Раскрывающийся список не отображается для уже выбранных значений. Это только для типа доступных, невыбранных значений.

Вот проблемы, с которыми я столкнулся до сих пор:

  • Выбранные теги не отображаются, если они не являются частью списка items.
  • Использование объектов тегов в виде массива с [(ngModel)] заставляет ng-select рассматривать его как значение, которого вообще не существует. ng-select, кажется, использует идентификаторы только для [(ngModel)], когда [mutiple]=true, в отличие от выбранного объекта, когда [multiple]=false
  • Наблюдаемая tagsInput$ не срабатывает, если [isOpen]=false

Я убедился, что tagsService работает правильно.

Текущий вид:

<ng-select [items]="tags$ | async"
           bindValue="name"
           [loading]="tagsLoading"
           [typeahead]="tagsInput$"
           [multiple]="true"
           [isOpen]="tagsOpen"
           [searchFn]="filterSelectedTags"
           [(ngModel)]="selectedTagIds"></ng-select>

Текущий контроллер:

class TagFormComponent {

  public tags$: Observable<Tag[]>;
  public tagsLoading: boolean;
  public tagsInput$: Subject<string>;
  public tagsChanger$: Subject<Tag[]>;
  public selectedTags: Tag[];
  public selectedTagIds: number[];
  public tagsOpen: boolean;

  constructor(private tagService: TagService) {

    this.tagsInput$ = new Subject<string>();
    this.tagsChanger$ = new Subject<Tag[]>();
    this.tagsChanger$.subscribe( tags => {
      this.selectedTagIds = tags.map(t => t.id);
      this.selectedTags = tags;
    });
    this.tags$ = concat(
      this.tagsChanger$,
      this.tagsInput$.pipe(
        debounceTime(200),
        distinctUntilChanged(),
        tap( () => {
          this.tagsOpen = true;
          this.tagsLoading = true;
        }),
        switchMap(q => this.tagService.search(q).pipe(
          catchError( err => { this.tagsLoading = false; console.error(err); return of([] ); }),
          tap( () => this.tagsLoading = false)
        ))
      )
    );

    this.tagsChanger$.next(this.assetGroup.tags);
  }

  public matcher(a: any, b: any): boolean {
    return !!a && b && a.id === b.id;
  }

  public filterSelectedTags(_q: string, item: Tag) {
    return !this.selectedTagIds.includes(item.id);
  }

  public tagAdded() {
    this.tagsOpen = false;
  }
}
...