I am working on angular selectionmodel where I have a search bar where user searches for list and selects items and if user closes the search keyword then previous selected values i.e., before search not getting selected in the selectionmodel list.
Search code in ts:
searchUsers(filterValue: string) {
this.previousSelectedValues = this.userSelection.selected;
console.log("came to searchUsers",filterValue);
this.searchKey = filterValue;
let params = { 'searchData': this.searchKey}
this.commCenterService.getSearchedUsers(params).subscribe((res)=>{
console.log("Search Response: Users",res);
this.users = res;
console.log("previous selected fields",this.userSelection.selected);
if(filterValue == ""){
this.previousSelectedValues.forEach(row => this.userSelection.select(row));
}
this.dataSource = new MatTableDataSource(this.users);
});
}
selectionmodel initialization code:
userSelection = new SelectionModel<AddRecipientsList>(true, []);
/** Whether the number of selected elements matches the total number of rows. */
isAllSelected() {
const numSelected = this.userSelection.selected.length;
const numRows = this.dataSource.data.length;
return numSelected === numRows;
}
/** Selects all rows if they are not all selected; otherwise clear selection. */
masterToggle() {
this.isAllSelected() ?
this.userSelection.clear() :
this.dataSource.data.forEach(row => this.userSelection.select(row));
}
/** The label for the checkbox on the passed row */
checkboxLabel(row?: PeriodicElement): string {
if (!row) {
return `${this.isAllSelected() ? 'select' : 'deselect'} all`;
}
}
HTML:
<div fxFlex="auto" fxLayoutAlign="start center" fxLayoutGap="10px">
<mat-form-field fxFlex="100" appearance="outline">
<input matInput type="text" (keydown.enter)="searchUsers(value)" [(ngModel)]="value">
<mat-label fxLayoutAlign="start center">
<mat-icon class="s-16">search</mat-icon>Search by Recipient Name, Email
</mat-label>
<button mat-button *ngIf="searchKey" matSuffix mat-icon-button aria-label="Clear" (click)="value=''; searchUsers(value);">
<mat-icon class="s-16">close</mat-icon>
</button>
</mat-form-field>
</div>
<div>
<mat-table [dataSource]="dataSource" class="display-table">
<!-- Checkbox Column -->
<ng-container matColumnDef="select">
<mat-header-cell *matHeaderCellDef>
<mat-checkbox (change)="$event ? masterToggle() : null"
[checked]="userSelection.hasValue() && isAllSelected()"
[indeterminate]="userSelection.hasValue() && !isAllSelected()" [aria-label]="checkboxLabel()">
</mat-checkbox>
</mat-header-cell>>
<mat-cell *matCellDef="let row">
<mat-checkbox (click)="$event.stopPropagation()" (change)="$event ? userSelection.toggle(row) : null"
[checked]="userSelection.isSelected(row)" [aria-label]="checkboxLabel(row)">
</mat-checkbox>
</mat-cell>>
</ng-container>
<!-- recepientName Column -->
<ng-container matColumnDef="recepientName">
<mat-header-cell *matHeaderCellDef> recepient Name </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
</ng-container>
<!-- recepientEmail Column -->
<ng-container matColumnDef="recepientEmail">
<mat-header-cell *matHeaderCellDef> recepient Email </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.email}} </mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
</div>
I am able to get my previous selected list from this.userSelection.selected
My selection/previous selected List is below:
previous selected fields
0:
email: "[email protected]"
name: "some name"
1:
email: "[email protected]"
name: "some name"
How does this work? Any Idea? Thanks.
SelectionModel holds references to objects. Therefore when you re-initialize this.dataSource
in searchUsers
function, references to actual objects in this.userSelection
gets lost. In order to overcome this in your use case you have to re-initialize this.userSelection
with new objects in new this.dataSource
However, since your search returns different lists; it may not be possible to find previous user items in new search results. In this case i suggest using a primitive value (which acts as a unique id for user objects) for keeping elements in SelectionModel. Such that;
selection.toggle(row.email) /** when selecting/de-selecting elements*/
and
selection.isSelected(row.email) /** when checking if an element is selected */
Please note that; i suggest removig master toggle to select/unselect all elements because your list changes at every search and selecting/unselecting all in different lists seems a bit ambiguous in a user point of view.
I also created a demo here;
https://stackblitz.com/edit/angular-e9brcp
in your html, update this part
<mat-checkbox (click)="$event.stopPropagation()" (change)="$event ? userSelection.toggle(row) : null"
[checked]="userSelection.isSelected(row)" [aria-label]="checkboxLabel(row)">
</mat-checkbox>
to this
<mat-checkbox (click)="$event.stopPropagation()" (change)="$event ? userSelection.toggle(row.email) : null"
[checked]="userSelection.isSelected(row.email)">
</mat-checkbox>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With