Angular CDK拖拽表单组时currentIndex始终为0的问题
Angular CDK表单组拖拽
currentIndex始终为0的问题解决 已实现Angular CDK表单组内字段跨组拖拽,但拖拽整个表单组时,currentIndex始终显示为0,previousIndex正常,无法正确调整表单组顺序。
问题原因
- 外层表单组的
cdkDropList未绑定[cdkDropListData],CDK无法关联到目标数组dummyFormData.fieldGroups,导致位置计算错误。 - 表单组内部嵌套了字段的
cdkDropList,拖拽时CDK可能误识别触发元素,干扰外层容器的位置判断。 dropNewGroup方法中直接调用dropGroup的逻辑有误,新增组后未正确处理拖拽事件索引。
解决方案
1. 修正外层cdkDropList配置
给外层表单组容器绑定[cdkDropListData],并给表单组的cdkDrag指定根元素,避免内部嵌套容器干扰:
<div cdkDropListGroup class="overall-container flex-row"> <!-- 外层表单组拖拽容器:绑定数据源,指定垂直拖拽方向 --> <div class="flex-grow admin-grid-layout padding-right-regular" cdkDropList [cdkDropListData]="dummyFormData.fieldGroups" (cdkDropListDropped)="dropGroup($event)" cdkDropListOrientation="vertical"> <!-- 表单组拖拽项:指定根元素为当前容器,避免内部cdkDropList触发拖拽 --> <div cdkDrag cdkDragRootElement=".section-container" *ngFor="let group of dummyFormData.fieldGroups; let i = index" class="entity-form-cell admin-form-column section-container"> <app-admin-section-header [(title)]="group.header" (remove)="removeGroup(i)"></app-admin-section-header> <!-- 内部字段拖拽容器保持原有配置 --> <div cdkDropList [cdkDropListData]="group.fields" (cdkDropListDropped)="drop($event)" class="fields-group-list drop-list"> <div *ngFor="let field of group.fields" class="admin-form-field flex-row align-center" cdkDrag cdkDragBoundary=".overall-container"> <div class="dummy-form-field"></div> </div> </div> </div> </div> <!-- 新增组区域移到外层cdkDropList外部,避免干扰索引计算 --> <div class="entity-form-cell admin-form-column"> <div cdkDropList (cdkDropListDropped)="dropNewGroup($event)" class="fields-group-list drop-list drop-area-hint"> drop here to create new field group </div> </div> <!-- 右侧工具栏保持不变 --> <mat-card class="toolbar"> <mat-card-content cdkDropList (cdkDropListDropped)="drop($event)" [cdkDropListData]="dummyFormData.availableFields" class="drop-list"> <div class="drop-area-hint"></div> </mat-card-content> </mat-card> </div>
2. 修正TypeScript方法逻辑
确保操作组件内的数据源,调整dropNewGroup的逻辑:
// 假设dummyFormData是组件类属性(避免全局变量) dummyFormData = { fieldGroups: [ { fields: ['photo'], header: "Personal Information" }, { fields: ['name', 'projectNumber', 'admissionDate'], header: "Additional" }, { fields: ['dateOfBirth', 'birth_certificate', 'gender', 'motherTongue'], header: "Additional" }, { fields: ['center', 'status', 'address', 'phone'], header: "Scholar activities" } ], availableFields: ['field1', 'field2', 'field3'], createNewFieldPlaceholder: 'createNewFieldPlaceholder' }; dropGroup(event: CdkDragDrop<any[]>) { moveItemInArray( this.dummyFormData.fieldGroups, event.previousIndex, event.currentIndex, ); } dropNewGroup(event: CdkDragDrop<any>) { const newCol = { fields: [], header: "New Group" }; this.dummyFormData.fieldGroups.push(newCol); // 若拖拽现有组到此处,调整其位置到数组末尾 if (event.previousContainer.data === this.dummyFormData.fieldGroups) { moveItemInArray( this.dummyFormData.fieldGroups, event.previousIndex, this.dummyFormData.fieldGroups.length - 1 ); } } removeGroup(i: number) { this.dummyFormData.fieldGroups.splice(i, 1); } // 原有drop方法保持不变 drop(event: CdkDragDrop<any[]>) { // ... 你的原有逻辑 }
3. 关键注意点
cdkDropList必须绑定[cdkDropListData],CDK依赖该属性关联目标数组,才能正确计算拖拽索引。- 嵌套拖拽场景下,用
cdkDragRootElement指定拖拽根元素,避免内部cdkDropList/cdkDrag干扰外层拖拽判断。 - 新增组区域不要放在外层表单组的
cdkDropList内部,否则会被算作容器内的一个项,导致索引计算混乱。
内容的提问来源于stack exchange,提问作者Abhishek Negi
相关产品推荐
相关产品推荐

