Search code examples
angularhtmldrag-and-dropangular-materialangular7

How to customize the CSS in Angular material 7 drag and drop while dragging, drag preview and drag placeholder?


I have found some basic examples of how to use .cdk-drag-preview and .cdk-drag-placeholder classes and they seem to do the job when there are no nested elements.

Basically, I have a list of actions and each action is represented in a complex mat-card format. That portion is actually done as another component but for the sake of this example, I will make it as basic as I possibly can.

My example is similar to this structure:

<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>

In angular component

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
}

I want to be able to do the following:

  • While dragging a card to the left change its border color to blue, and green when dragging right
  • Change border color accordingly for drag placeholder.

The issue of using .cdk-drag-preview and .cdk-drag-placeholder seems to apply to the draggable div (parent of mat-card); whereas, I am trying to change its child's border color.

Thanks in advance :)

ADDENDUM

My most important challenge is to change the border color in the drag-placeholder. I am trying to change placeholder's border color and left margin to indicate the user the action has moved to left or right, representing different levels within the list.


Solution

  • Would something like below accomplish your goal?

    Initialize nativeElement x and 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;
      }
    

    Compare X offset and use rendere2 to set style on nativeElement

    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');
        }
      }
    

    Revision:

    To change color while dragging do the following.

    Get reference to #cdkDropList in the view.

    @ViewChild('cdkDropList') _dropList:any;
    

    Set index in *ngFor

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

    Pass index to function

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

    Receive index and reach into the children of the cdkDropList to set the style.

    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