Angular KendoGrid新增行后拖拽排序失效问题求助
问题:Kendo Grid动态新增行后行重排功能异常
在Angular项目中使用带数据源的Kendo Grid,已设置rowReorderable=true开启行重排。网格加载完成后,初始行可正常拖拽调整顺序,但动态新增行后,无法将其他行拖拽到新增行的位置,仅能在最初的几行上操作。
已在测试示例中通过this.gridData = [...this.gridData, ...samplecustomers]的方式修复,但该方案在主项目中无效。主项目相关代码如下:
组件逻辑代码
openTagSelectionPopup() { this.popupService.showEntitySelectionPopup<BaseTag>({ title: this.translate.get('i18n:LABEL.TAG_SELECTION'), entitySet: 'UserBaseTags', singleEntitySet: 'BaseTags', includes: 'Asset.AssetType,MeasurementUnit.Measurement', sort: [{ field: 'Asset.Path', dir: 'asc' }, { field: 'Name', dir: 'asc' }], multiSelect: true, selectionRequired: false, columns: [ { field: 'Asset.Path', title: this.translate.get('i18n:TAG.ASSET'), filterable: true }, { field: 'Name', title: this.translate.get('i18n:TAG.NAME'), filterable: true }, { field: 'MeasurementUnit.Name', title: this.translate.get('i18n:TAG.MEASUREMENT_UNIT'), filterable: true }, { field: 'MeasurementUnit.Symbol', title: this.translate.get('i18n:TAG.MEASUREMENT_UNIT.SYMBOL'), filterable: true } ] }).subscribe({ next: result => { if (result && result.length) { let addedItems: DataSourceProductionConsumptionItemTag[] = []; result.forEach((tag: BaseTag) => { if (findIndex(this.items, (item: DataSourceProductionConsumptionItemTag) => item.TagId == tag.Id) == -1) { addedItems.push({ TagId: tag.Id, Tag: tag, Category: '', Color: '#000000' }); } }); this.items = [...this.items, ...addedItems]; } } }); }
模板代码
<kendo-grid #itemsGrid [kendoGridBinding]="items" [height]="410" style="margin-bottom: 16px;" [rowReorderable]="true" kendoGridSelectBy="TagId" [(selectedKeys)]="selectedItemKeys" (cellClick)="cellClick($event)" (cellClose)="cellClose($event)"> <ng-template kendoGridToolbarTemplate> <button kendoButton look="outline" (click)="openTagSelectionPopup()">{{ 'i18n:DATASOURCE.TAGS.ADD' | translate }}</button> <button kendoButton look="outline" [disabled]="selectedItemKeys.length === 0" (click)="removeItems()">{{ 'i18n:DATASOURCE.TAGS.REMOVE' | translate }}</button> <kendo-formerror *ngIf="hasGridErr()">{{gridErr}}</kendo-formerror> </ng-template> <kendo-grid-rowreorder-column [width]="40"></kendo-grid-rowreorder-column> <kendo-grid-column [title]="translate.get('i18n:DATASOURCE.PRODUCTION_CONSUMPTION.TAG')" [field]="'TagId'"> <ng-template kendoGridCellTemplate let-dataItem let-rowIndex> {{ getTagDescription(dataItem) }} </ng-template> </kendo-grid-column> </kendo-grid>
新增行后UI显示正常,但拖拽功能仍存在异常。
解决方案
1. 设置TrackBy函数
Kendo Grid的默认变更检测可能无法正确识别新增行的唯一性,添加trackBy指令帮助Grid精准跟踪行数据的变化:
<kendo-grid #itemsGrid [kendoGridBinding]="items" [trackBy]="trackByTagId" ...>
在组件中实现对应的跟踪函数:
trackByTagId(index: number, item: DataSourceProductionConsumptionItemTag): number { return item.TagId; // 基于唯一标识TagId跟踪行 }
2. 手动触发Grid刷新
新增行后,强制Grid重新渲染并绑定拖拽事件,通过ViewChild获取Grid实例并调用refresh():
import { Component, ViewChild } from '@angular/core'; import { GridComponent } from '@progress/kendo-angular-grid'; @Component({/* 组件元数据 */}) export class YourComponent { @ViewChild('itemsGrid') itemsGrid: GridComponent; openTagSelectionPopup() { // ... 原有弹窗逻辑 this.items = [...this.items, ...addedItems]; // 等待DOM更新后执行刷新 setTimeout(() => { this.itemsGrid.refresh(); }); } }
3. 切换为Observable数据源
改用BehaviorSubject作为数据源,让Grid自动感知数据变化并更新行重排绑定:
import { BehaviorSubject } from 'rxjs'; export class YourComponent { private itemsSubject = new BehaviorSubject<DataSourceProductionConsumptionItemTag[]>([]); items$ = this.itemsSubject.asObservable(); // 初始化时传入初始数据 ngOnInit() { this.itemsSubject.next(yourInitialItems); } openTagSelectionPopup() { // ... 原有弹窗逻辑 const updatedItems = [...this.itemsSubject.value, ...addedItems]; this.itemsSubject.next(updatedItems); } }
模板中绑定Observable数据源:
<kendo-grid #itemsGrid [data]="items$" ...>
4. 检查行重排列的有效性
确保kendo-grid-rowreorder-column已正确添加到Grid模板中,没有被自定义样式或其他模板元素覆盖拖拽手柄的事件绑定。
内容的提问来源于stack exchange,提问作者Dylan
相关产品推荐
相关产品推荐

