Я использую ng-select , чтобы выбрать несколько значений из большого списка, который загружается удаленно, в зависимости от того, что пользователь вводит в поле. Вот мои требования:
- Метки добавляются динамически
- Раскрывающийся список не отображается для уже выбранных значений. Это только для типа доступных, невыбранных значений.
Вот проблемы, с которыми я столкнулся до сих пор:
- Выбранные теги не отображаются, если они не являются частью списка
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;
}
}