You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 12 Material CDK拖拽实现元素替换占位符功能咨询

调整步骤如下

1. 先修正HTML代码的两处问题

你当前给列表B(占位符列表)的拖拽属性配置有误,且需要禁止占位符被拖拽、禁止列表B内部排序,修改后代码如下:

<mat-drawer-container class="example-container">
  <mat-drawer class="sideMenu" mode="side" role="dragAndDrop" position="end" opened>
    <div class="sideNav-container">
      <!-- 列表A:可选拖拽源 -->
      <div 
        cdkDropList 
        #moviesList="cdkDropList" 
        [cdkDropListData]="MoviesList"
        [cdkDropListConnectedTo]="[doneMovieList]" 
        class="drag-list-sidenav" 
        (cdkDropListDropped)="onDrop($event)"
      >
        <div class="movie-block" *ngFor="let movie of MoviesList" cdkDrag>
          <span mat-raised-button
            matTooltip="bla"
            matTooltipPosition="left" class=""
          >{{movie}}</span>
        </div>
      </div>
    </div> 
  </mat-drawer>
  <mat-drawer-content class="sideMainContent">
    <div class="container">
      <!-- 列表B:占位符目标列表 -->
      <div 
        cdkDropList 
        #doneMovieList="cdkDropList" 
        [cdkDropListData]="MoviesWatched"
        cdkDropListSortingDisabled="true"
        class="movie-list" 
        (cdkDropListDropped)="onDrop($event)"
      >
        <!-- 加cdkDragDisabled禁止占位符被拖拽 -->
        <div class="movie-block" *ngFor="let watched of MoviesWatched" cdkDrag cdkDragDisabled>{{watched}}</div>
      </div>
    </div>
  </mat-drawer-content>
</mat-drawer-container>

2. 修改TS的onDrop逻辑

把默认的transferArrayItem插入逻辑换成替换逻辑,修改后代码如下:

import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';

export class ListComponent{
  MoviesList: string[] = [
    'The Far Side of the World',
    'Morituri',
    'Napoleon Dynamite',
    'Pulp Fiction',
    'Blade Runner',
    'Cool Hand Luke',
    'Heat',
    'Juice'
  ];

  MoviesWatched: string[] = [
    'shouled be Placeholde1',
    'shouled be Placeholde2',
  ];

  constructor(){}

  onDrop(event: CdkDragDrop<string[]>) {
    // 同容器拖拽:保留A内部排序逻辑,不需要可以删掉
    if (event.previousContainer === event.container) {
      moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
    } else {
      // 跨容器拖拽:执行替换逻辑
      // 1. 取出被拖拽的元素
      const draggedItem = event.previousContainer.data[event.previousIndex];
      // 2. 从原列表A删除对应元素
      event.previousContainer.data.splice(event.previousIndex, 1);
      // 3. 替换列表B对应位置的占位符
      event.container.data[event.currentIndex] = draggedItem;
    }
  }  
}

逻辑说明

  • 给列表B加了cdkDropListSortingDisabled="true"禁止内部元素排序,避免占位符顺序被打乱
  • 给列表B的每一项加了cdkDragDisabled禁止占位符被拖拽到其他列表
  • 跨容器拖拽时不再调用默认的transferArrayItem(该方法会给目标数组新增元素),而是直接替换目标数组对应索引的值,完全符合你要的替换占位符的需求
  • 如果你不需要列表A内部拖拽排序,可以直接删除同容器判断里的moveItemInArray逻辑

内容的提问来源于stack exchange,提问作者Der_V

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 21:54:04