Search code examples
angularangular-material2ng2-dragula

Drag and drop angular-material2 chips with ng2-dragula library


Using angular2 material and dragula, I want to drag and drop chips with ng2-dragula library.

Specifying the dragula containers:

<md-chip-list [dragula]="'bag-chips'">
  <md-chip>Chip 1</md-chip>
  <md-chip>Chip 2</md-chip>
</md-chip-list>

<md-chip-list [dragula]="'bag-chips'">
  <md-chip>Chip 3</md-chip>
  <md-chip>Chip 4</md-chip>
</md-chip-list>

The above doesn't work because Angular-material creates a wrapper div.md-chip-list-wrapper inside md-chip-list. When we attempt to drag and drop, the whole wrapper gets dragged.

I tried to fix the problem with dragula's isContainer method, but dragging didn't work at all.

constructor(private dragula: DragulaService) {
  dragula.setOptions('bag-chips', {
    isContainer(el) {
      return el.classList.contains('md-chip-list-wrapper');
    }
  }
}

I tried to fix the problem by adding a div wrapper inside md-chip-list, but that seems to error in angular material.

<md-chip-list>
  <div [dragula]="'bag-chips'">
    <md-chip>Chip</md-chip>
  </div>
</md-chip-list>

So how to make the md-chip-list work with ng2-dragula?


Solution

  • A dragula solution

    Using dragula options isContainer and direction seem to do the trick:

    // drake-example.component.ts
    constructor(private dragula: DragulaService) {
      dragula.setOptions('bag-chips', {
        isContainer(el) {
          return el.classList.contains('md-chip-list-wrapper');
        },
        direction: 'horizontal' // or 'vertical'
      }
    }
    
    <!-- drake-example.component.html -->
    <md-chip-list>
      <md-chip>Chip 1</md-chip>
      <md-chip>Chip 2</md-chip>
    </md-chip-list>
    
    <md-chip-list>
      <md-chip>Chip 3</md-chip>
      <md-chip>Chip 4</md-chip>
    </md-chip-list>
    

    Credits for a plunker go to @yurzui

    Warnings

    • The md-chip-list-wrapper class might need to be changed according to the current angular-material implementation.
    • The order of md-chips in md-chip-list doesn't update. i.e. after rearranging md-chips, navigating them with arrows will be confused (see the plunker above).

    The actual solution (digression)

    I went with ng2-dnd library. It provides dnd-draggable and dnd-droppable directives to explicitly state which elements can be dragged and where they can be dropped.

    Overall, the solution is more complex, but also more customizable and intuitive. The draggable doesn't have to be the immediate parent of the droppable.