如何在拖放时自定义Angular Material 7中的CSS,包括拖动预览和拖动占位符?

9

我找到了一些如何使用.cdk-drag-preview.cdk-drag-placeholder类的基本示例,当没有嵌套元素时,它们似乎能够完成任务。

基本上,我有一个操作列表,每个操作都以复杂的mat-card格式表示。那部分实际上是另一个组件完成的,但为了这个示例,我将尽可能简单地呈现它。

我的示例与以下结构类似:

<style>
    .my_action { border: 2px solid red; }
</style>

<div class="drop_area" cdkDropList>
    <div *ngFor="let action of actions"
        (cdkDragStarted)="dragStart($event, action)"
        (cdkDragMoved)="dragMoved($event, action)"
        (cdkDragEnded)="dragEnded($event, action)" cdkDrag>

        <mat-card class="my_action">
            {{ action.name }}
        </mat-card>

    </div>
</div>

在Angular组件中
dragStart(e, action) { 
    // initialize start X coord
    this.startX = 0;

    // initialize start Y coord
    this.startY = 0;
}

dragMoved(e, action) {
    // record new position
    this.endX = e.pointerPosition.x;
    this.endY = e.pointerPosition.y;

    // logic to set startX and startY
    // TRYING TO CHANGE CARD BORDER COLOR IF this.endX - this.startX > some number
}

我希望能够实现以下操作:
  • 当将卡片向左拖动时,将其边框颜色更改为蓝色,向右拖动时则更改为绿色
  • 相应地更改拖放占位符的边框颜色。
使用 ".cdk-drag-preview" 和 ".cdk-drag-placeholder" 的问题似乎适用于可拖动的 "div" (mat-card 的父级); 而我正在尝试更改它的子元素的边框颜色。
提前感谢 :) 补充说明 我的最重要的挑战是更改拖放占位符的边框颜色。 我正在尝试更改占位符的边框颜色和左边距,以告知用户操作已向左或向右移动,表示列表中不同的级别。

你尝试过这个选择器吗?.cdk-drag-preview mat-card,.cdk-drag-placeholder mat-card {} - onik
@onik 我已经尝试过了,但它不起作用。我感觉当你拖动一张卡片时,Material会为预览制作一个不同的复制结构,我似乎无法连接到该元素以动态更改其CSS。 - Brian
3个回答

7

下面的内容是否可以达到您的目标?

初始化nativeElement的x和y值

dragStart(e, action) {
    const rect = e.source.element.nativeElement.getBoundingClientRect();

    // initialize start X coord
    this.startX = rect.x;
    // initialize start Y coord
    this.startY = rect.y;
  }

比较X轴偏移量,并使用rendere2nativeElement上设置样式。
dragMoved(e, action) {
    // record new position
    this.currentX = e.event.clientX;
    this.currentY = e.event.clientY;
    // logic to set startX and startY
    // TRYING TO CHANGE CARD BORDER COLOR IF this.endX - this.startX > some number
    if(this.startX < this.currentX){
      this._renderer.setStyle(e.source.element.nativeElement, 'border-style', 'solid');
      this._renderer.setStyle(e.source.element.nativeElement, 'border-color', 'green');
    }
    else if (this.startX > this.currentX){
      this._renderer.setStyle(e.source.element.nativeElement, 'border-style', 'solid');
      this._renderer.setStyle(e.source.element.nativeElement, 'border-color', 'blue');
    }
  }

修订:

要在拖动时更改颜色,请执行以下操作。

在视图中获取对#cdkDropList的引用。

@ViewChild('cdkDropList') _dropList:any;

*ngFor 中设置索引

*ngFor="let action of actions; let i = index"

将索引传递给函数

(cdkDragMoved)="dragMoved($event, action, i)"

接收索引并进入cdkDropList的子项以设置样式。

dragMoved(e, action, i) {
    // record new position
    this.currentX = e.event.clientX;
    this.currentY = e.event.clientY;
    // logic to set startX and startY
    // TRYING TO CHANGE CARD BORDER COLOR IF this.endX - this.startX > some number
    if(this.startX < this.currentX){
      this._renderer.setStyle(this._dropList.nativeElement.children[i], 'border-style', 'solid');
      this._renderer.setStyle(this._dropList.nativeElement.children[i], 'border-color', 'green');
    }
    else if (this.startX > this.currentX){
      this._renderer.setStyle(this._dropList.nativeElement.children[i], 'border-style', 'solid');
       this._renderer.setStyle(this._dropList.nativeElement.children[i], 'border-color', 'blue');
    }
  }

Stackblitz

https://stackblitz.com/edit/angular-hdskvc?embed=1&file=app/cdk-drag-drop-overview-example.ts


问题在于当你放下卡片后,它才会改变颜色。我正在尝试在拖动卡片时改变颜色。 - Brian
请查看修订后的 StackBlitz 和答案。 - Marshal
谢谢,这已经接近了。让我上班后再仔细看一下 ;) 努力加1分。 - Brian
我接受这个答案,因为使用 #cdkDropList 和 Renderer2 已经足够帮我完成任务了。 - Brian

1
当拖动cdkDrag元素时,它将创建一个预览元素,该元素在拖动时可见。这将是原始元素的克隆。克隆元素将删除其id属性,并添加类.cdk-drag-preview。
谨慎使用cdkDragMoved事件,因为此事件将为用户拖动的每个像素触发一次。
<div cdkDropList class="example-list">
    <div class="example-box" *ngFor="let action of actions" cdkDrag 
        (cdkDragStarted)="dragStart($event)"
        (cdkDragMoved)="dragMoved($event)">
        {{ action.name }}
    </div>
</div>

export class CustomComponent {
    cloned: any;

    actions = [
        { name: "one" },
        { name: "two" },
        { name: "three" }
    ];

    constructor(private _renderer: Renderer2) { }

    dragStart(event) {
        this.cloned = document.getElementsByClassName("cdk-drag-preview")[0];
    }

    dragMoved(event) {
        this._renderer.removeClass(this.cloned, "red");
        this._renderer.removeClass(this.cloned, "green");

        const distance: { x: number, y: number } = event.distance;
        this._renderer.addClass(this.cloned, (distance.x > 0) ? "green" : "red");
    }
}

0
你可以这样做:
<div class="drop_area" cdkDropList>
<div *ngFor="let action of actions;let i = index;"
    (cdkDragStarted)="dragStart($event, action)"
    (cdkDragMoved)="dragMoved($event, action, i)"
    (cdkDragEnded)="dragEnded($event, action)" cdkDrag>

    <mat-card class="my_action{{i}}">
        {{ action.name }}
    </mat-card>

</div>

dragMoved(e, action, index: number) {
    // record new position
    this.endX = e.pointerPosition.x;
    this.endY = e.pointerPosition.y;

    // login to set startX and startY
    // TRYING TO CHANGE CARD BORDER COLOR IF this.endX - this.startX > some number

   document.getElementsByClassName('my_action'+index)[0].style.borderColor='blue';
}

我会研究一下,我想我试过类似的事情。但我最重要的挑战是改变拖放占位符的边框颜色。 - Brian
你知道,我正试图改变占位符的边框颜色和左间距,以向用户指示操作已经向左或右移动,代表列表中不同的级别。 - Brian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接