ng-multiselect-dropdown编程清空选中项视图未同步更新问题
问题根因
ng-multiselect-dropdown组件内部维护了独立的选中态缓存,默认只在组件内置的选中/取消选中交互触发时,才会同步更新内部缓存和视图层。外部直接修改绑定的selectedItems数组、或通过响应式表单设值时,组件不会自动同步内部缓存,加上组件默认使用OnPush变更检测策略,引用变更没有触发视图重绘,就会出现变量已清空、视图仍显示选中的状态不同步问题。
另外现有代码存在3个会放大该问题的写法错误:
- 同时使用
formControlName和[(ngModel)]做双向绑定,两套状态管理逻辑冲突 @ViewChild的选择器和模板不匹配,没有正确拿到组件实例- 响应式表单组
multiselect中没有定义multi控件,表单绑定本身不生效
修复方案
1. 修正模板代码
给组件添加模板引用变量,删除冲突的ngModel绑定:
<form [formGroup]="multiselect" (ngSubmit)="onSubmit()"> <div> <ng-multiselect-dropdown #multiDropdown [placeholder]="''" [settings]="settings" [data]="propertiesCharUnique" (onSelect)="onItemSelect($event)" (onSelectAll)="onSelectAll($event)" (onDeSelect)="onDeSelect($event)" (onDeSelectAll)="onDeSelectAll($event)" formControlName="multi" > </ng-multiselect-dropdown> <input type="submit" value="Load Targets" /> </div> </form>
2. 修正TS逻辑
正确获取组件实例,补全表单控件定义,清空时同步调用组件内置方法、手动触发变更检测:
import { Component, ViewChild, ChangeDetectorRef } from '@angular/core'; import { FormBuilder } from '@angular/forms'; import { NgMultiSelectDropDownComponent } from 'ng-multiselect-dropdown'; @Component({ // 你的组件元配置 }) export class YourComponent { // 正确通过模板变量获取组件实例 @ViewChild('multiDropdown') multiDropdown!: NgMultiSelectDropDownComponent; // 补全表单控件定义,给multi控件设置初始空数组 multiselect = this.formBuilder.group({ multi: [[]] }); constructor( private formBuilder: FormBuilder, private cdr: ChangeDetectorRef ) {} public reset(){ // 重置表单控件值 this.multiselect.get("multi")?.setValue([]); // 调用组件内置clearAll方法,同步组件内部选中态缓存 this.multiDropdown.clearAll(); // 手动触发变更检测,强制视图更新 this.cdr.detectChanges(); } // 其他业务逻辑:onItemSelect、onSelectAll、onSubmit等 }
3. 极端场景兼容
如果执行上述操作后仍存在视图缓存问题,可以在清空逻辑末尾追加一行代码,强制组件重新加载数据源触发重绘:
// 浅拷贝原数据源,改变引用触发组件输入变更检测 this.propertiesCharUnique = [...this.propertiesCharUnique];
注意事项
- 不要在响应式表单中混用
[(ngModel)],该写法从Angular 6开始已不被官方推荐,极易引发状态不同步问题 - 组件配置
settings中不要开启和清空逻辑冲突的配置项(例如singleSelection: true会自动禁用全选/清空相关的内部方法) - 若使用懒加载数据源,要确保清空操作时数据源已经完成初始化,否则组件实例方法可能执行失败
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

