Kendo Autocomplete显示[object Object],不使用setTimeout如何修复
问题根因
- 模板绑定存在语法错误与冲突:kendo-autocomplete 组件同时声明了
[(ngModel)]双向绑定和错误的[value]绑定([value]属性内重复嵌套了[(ngModel)]语法),导致组件取值逻辑混乱,优先读取到了选中的对象而非格式化后的字符串。另外模板中click事件引用的模板变量名错误,声明的是#dropDownList却写为dropDownValue.value。 - 数组索引赋值无法触发变更检测:Angular 默认变更检测无法识别数组通过索引直接赋值的内容变更,
setTimeout本质是触发了下一轮宏任务后的全局变更检测才让渲染生效。 - Kendo Autocomplete 默认返回值逻辑:如果你的
aDirectoryData是对象数组且未指定valueField或valuePrimitive,valueChange事件默认返回选中的完整对象,未转字符串直接渲染就会显示为[object Object]。
解决方案
1. 修复模板绑定
删除重复错误的 [value] 绑定,修正模板变量引用,根据数据源类型补充对应配置:
<ng-template kendoGridCellTemplate let-dataItem="dataItem" let-rowIndex="rowIndex"> <kendo-autocomplete #dropDownList [data]="aDirectoryData" [clearButton]="true" [(ngModel)]="addressDisplayValue[rowIndex]" [disabled]="dataItem.isErroredItem" [allowCustom]="true" <!-- 若数据源是对象数组,只需要展示对象的某个字段可配置valueField,或者配置valuePrimitive让组件直接返回字符串值 --> [valuePrimitive]="true" (keyup)="fShippingAddressAutoComplete($event)" (valueChange)="onValue($event, rowIndex, dataItem)" <!-- 修正模板变量引用 --> (click)="fShippingAddress(dropDownList.value)" (focus)="dropDownList.toggle()"> </kendo-autocomplete> </ng-template>
如果需要基于选中对象的属性拼接展示文本,不需要配置 valuePrimitive,直接在 onValue 方法中取 shippingAdd 对象的对应字段拼接即可。
2. 手动触发变更检测(无需setTimeout)
注入 Angular 内置的 ChangeDetectorRef 手动触发当前组件的变更检测:
import { ChangeDetectorRef } from '@angular/core'; // 组件构造器注入 constructor(private cdr: ChangeDetectorRef) {} addressDisplayValue: string[] = []; onValue(shippingAdd: IShipToAddresses, rowIndex: number, dataItem: ISalesOrderGroups): void { // 如果需要用选中对象的属性,直接取shippingAdd的对应字段即可,比如const shippingId = shippingAdd.id const shippingId = 'abcd'; const displayText = `${shippingId} defgh`; this.addressDisplayValue[rowIndex] = displayText; // 手动标记组件需要变更检测 this.cdr.markForCheck(); }
3. 替换数组赋值方式
通过修改数组引用的方式让 Angular 自动识别变更,不需要手动调用变更检测API:
onValue(shippingAdd: IShipToAddresses, rowIndex: number, dataItem: ISalesOrderGroups): void { const shippingId = 'abcd'; const displayText = `${shippingId} defgh`; // 生成新数组触发变更检测 this.addressDisplayValue = [ ...this.addressDisplayValue.slice(0, rowIndex), displayText, ...this.addressDisplayValue.slice(rowIndex + 1) ]; }
内容的提问来源于stack exchange,提问作者Amit Kumar
相关产品推荐
相关产品推荐

