I have been searching around for a solution for this but cant figure it out how this should me made. Here is a stackblitz of what im almost looking for, but i dont want it to appear like a dropdown list. https://stackblitz.com/edit/angular-yo2o9o?file=app%2Fapp.component.html
I would love to have a list like my own code below, but implement a search field over the list and use it to filter users$ depending on the input (but still saving the selected users) ...
Edit: Found this one, https://stackblitz.com/edit/angular-i3pfu2-xgembc?file=app%2Flist-selection-example.ts,
This is how it should look, but i cant get this to work with my code..
Html:
<div class="userContainer">
<p>Choose participants</p>
<mat-selection-list class="form-group" #selectedUsers formControlName="users">
<mat-list-option *ngFor="let user of users$ | async" [value]="user">
{{ user.name }}
</mat-list-option>
</mat-selection-list>
<p>Invited users: {{ selectedUsers.selectedOptions.selected.length }}</p>
</div>
users$ is coming from an selector from my state
this.store$.dispatch(new fromUsers.GetUsers());
this.users$ = this.store$.pipe(select(fromUsers.getRelevantUsers(+this.userId)));
And this is the form i'm using..
createEventForm() {
this.eventForm = this.fb.group(
{
users: [null],
more inside...
}
);
}
A "filter search" is't only a FormControl, you subscribe to valueChanges and, using switchMap and debounce return a list, well, in code. If you has an array of values and a formControl
search = new FormControl();
typesOfShoes: string[] = ["Boots","Clogs","Loafers","Moccasins","Sneakers"];
You create an observable
$search = this.search.valueChanges.pipe(
startWith(null),
debounceTime(200),
switchMap((res: string) => {
if (!res) return of(this.typesOfShoes);
res = res.toLowerCase();
return of(
this.typesOfShoes.filter(x => x.toLowerCase().indexOf(res) >= 0)
);
})
);
And use
<mat-form-field >
<mat-label>Search</mat-label>
<input matInput [formControl]="search">
</mat-form-field>
<mat-selection-list #shoes [formControl]="shoesControl">
<mat-list-option *ngFor="let shoe of $search|async" [value]="shoe">
{{shoe}}
</mat-list-option>
</mat-selection-list>
See stackblitz
Updated As Charlie point, the problem is that if we change the search, you loose the values checked, so we can NOT use [formControl]="shoesControl"
So, we are going to use the event (selectionChange) of the mat-list and the property [selected] of the mat-option to change the value of the FormControl
So, we are going to has
<mat-selection-list #shoes
(selectionChange)="selectionChange($event.option)" >
<mat-list-option *ngFor="let shoe of $search|async"
[value]="shoe" [selected]="shoesControl.value &&
shoesControl.value.indexOf(shoe)>=0">
{{shoe}}
</mat-list-option>
</mat-selection-list>
See that there're no [formControl], but remember that a FormControl exist if we has an input or not. Well the function selectionChange received as argument an object with the property selected and value, so we has
selectionChange(option:any)
{
let value=this.shoesControl.value || []
if (option.selected)
value.push(option.value)
else
value=value.filter((x:any)=>x!=option.value)
this.shoesControl.setValue(value)
}
NOTE: I updated the stackblitz