Angular Material手动取消复选框状态问题求助
Let's break down why your checkboxes stay selected even after removing roles, and how to fix this cleanly:
The Root Cause
Your current logic only updates the currentRoles array when adding/removing roles, but you're not syncing these changes to the roleId FormControl bound to your "Add additional Roles" mat-select. Angular Material's mat-select gets its selected state directly from the linked FormControl's value—so until you update that value, the checkboxes will remain checked even if the role is gone from currentRoles.
Step-by-Step Solution
1. Pass Role Objects Directly (Stop Using DOM-Based Data Fetching)
First, ditch the fragile DOM element parsing (like selectedRoleOrGroup.path[1].id)—it's error-prone and hard to maintain. Instead, pass the actual role object to your addOrRemoveRole method:
Update your additional roles mat-option:
<mat-option *ngFor="let userRole of userRoleList" [value]="{ submitValue: userRole.SYS_RoleID, formValue: userRole.Role }" (click)="addOrRemoveRole(userRole)" id="{{ userRole.SYS_RoleID }}" > {{ userRole.Role }} </mat-option>
And update the Remove button to pass the role object too:
<li *ngFor="let role of currentRoles" id="{{ role.SYS_RoleID }}"> <span>{{ role.Role }}</span> <span style="background:lightblue" (click)="addOrRemoveRole(role)">Remove</span> </li>
2. Sync FormControl Value with currentRoles
Modify your addOrRemoveRole method to update the roleId FormControl whenever you modify currentRoles. Here's the revised method:
addOrRemoveRole(selectedRoleOrGroup: any) { // Handle Role Group selection if (selectedRoleOrGroup.SYS_RoleGroupID) { if (this.roleGroupId.value.length === 0) { this.currentRoles = []; // Reset roleId FormControl when deselecting role group this.roleId.setValue([]); } else { this.currentRoles = this.roleGroupDummyData; // Sync roleId FormControl with role group roles const roleIds = this.roleGroupDummyData.map(role => ({ submitValue: role.SYS_RoleID, formValue: role.Role })); this.roleId.setValue(roleIds); } this.userRoleList = this.filterRoles(this.userRoleListMaster, this.currentRoles); return; } // Handle individual roles const selectedUserRole = selectedRoleOrGroup; const roleExists = this.currentRoles.some(role => role.SYS_RoleID === selectedUserRole.SYS_RoleID); if (roleExists) { // Remove role from currentRoles this.currentRoles = this.currentRoles.filter(role => role.SYS_RoleID !== selectedUserRole.SYS_RoleID); // Remove role from roleId FormControl const updatedRoleValues = this.roleId.value.filter( roleVal => roleVal.submitValue !== selectedUserRole.SYS_RoleID ); this.roleId.setValue(updatedRoleValues); } else { // Add role to currentRoles this.currentRoles = [...this.currentRoles, selectedUserRole]; // Add role to roleId FormControl const newRoleValue = { submitValue: selectedUserRole.SYS_RoleID, formValue: selectedUserRole.Role }; this.roleId.setValue([...this.roleId.value, newRoleValue]); } }
3. Verify FormControl Initialization
Double-check that your roleId FormControl is properly set up in your form group (usually in ngOnInit):
// Example form initialization this.yourForm = this.formBuilder.group({ // ... other form controls roleId: [[], Validators.required] });
Why This Works
By updating the roleId FormControl's value alongside currentRoles, you ensure the mat-select's selected state always matches the roles displayed in "Current Roles". Angular Material automatically syncs checkbox states with the FormControl's value—no manual checkbox manipulation needed.
内容的提问来源于stack exchange,提问作者Matt Wendzina

