I'm using ng-select to select multiple values from a large list that is remotely loaded depending on what the user types in the box. Here are my requirements:
- Tags added dynamically
- Dropdown is not displayed for already selected values. It is only for typeahead of available, unselected values.
Here are the problems that I've run into so far:
- Selected tags do not get displayed if not part of the
items
list. - Using the tag objects as an array with
[(ngModel)]
makesng-select
treat it like the value doesn't exist at all.ng-select
seems to only use IDs for[(ngModel)]
when[mutiple]=true
, as opposed to the selected object when[multiple]=false
- The
tagsInput$
observable doesn't get fired if[isOpen]=false
I have verified that tagsService
is operating correctly.
Current View:
<ng-select [items]="tags$ | async"
bindValue="name"
[loading]="tagsLoading"
[typeahead]="tagsInput$"
[multiple]="true"
[isOpen]="tagsOpen"
[searchFn]="filterSelectedTags"
[(ngModel)]="selectedTagIds"></ng-select>
Current Controller:
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;
}
}