Components: [Drag and Drop] cdkDragHandle ignored when it is placed inside a child component

Created on 24 Oct 2018  路  16Comments  路  Source: angular/components

Bug, feature request, or proposal:

Bug

What is the expected behavior?

cdkDragHandle is correctly bound to its cdkDrag and it is the only element which allows cdkDrag to be moved, even when cdkDragHandle is specified inside a child component

What is the current behavior?

When cdkDragHandle is not placed directly in the same component as cdkDrag, but in a child component, it won't be bound to its cdkDrag. The entire cdkDrag can be used to move the element, not only the cdkDragHandle.

What are the steps to reproduce?

https://stackblitz.com/edit/angular-ckyzbp

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

Material 7.0.1

Most helpful comment

A work around for some limited cases is to project the element that holds the cdkDragHandle from the parent component to the child component and use ng-content to place it correctly within the child. Works for my simple case.

In the parent component template:

<mat-list cdkDropList (cdkDropListDropped)="dropped($event)">
  <mat-list-item ngFor="let item of items" cdkDrag [cdkDragData]="item">
    <child [item]="item">
      <button mat-flat-button color="grey">
        <mat-icon cdkDragHandle>unfold_more</mat-icon>
      </button>
    </child>
  </mat-list-item>
</mat-list>

Then in the child component template:

<div>Move me from here -></div><ng-content></ng-content>

All 16 comments

When the handle is inside the template of another component, there's no way for cdkDrag to find it since it uses ContentChildren.

Does this mean that for complex applications of columns and cards (with complex logic at all levels)... the whole drag and drop page needs to be rolled into the one component?

I need it too, my draggable items are complex children component, I need to put the cdkDragHandle inside the template of the draggable items...

A work around for some limited cases is to project the element that holds the cdkDragHandle from the parent component to the child component and use ng-content to place it correctly within the child. Works for my simple case.

In the parent component template:

<mat-list cdkDropList (cdkDropListDropped)="dropped($event)">
  <mat-list-item ngFor="let item of items" cdkDrag [cdkDragData]="item">
    <child [item]="item">
      <button mat-flat-button color="grey">
        <mat-icon cdkDragHandle>unfold_more</mat-icon>
      </button>
    </child>
  </mat-list-item>
</mat-list>

Then in the child component template:

<div>Move me from here -></div><ng-content></ng-content>

I also need this, I have a list of dynamically rendered components that I want to drag around in the page. cdkDragHandle is exactly what I need, but I cannot use it the way it's implemented now.

This is a must have for any website

Yes we need this too, also having cdkDropList in a parent component and cdkDrag (and cdkDragHandle) in a child component.

I'll add my vote as well, structuring a complex app requires us to use child components without cdkDrag falling apart.

Vote ++ I need it desperately! Also, the workaround does not work for me.

Gets my vote, not ideal having to keep everything in parent component. Makes it unusable in a lots of cases.

Also would love this feature. We are rendering a complex table that contains a component per cell in the component. We only want the first row of columns to be able to drag the table to reorder it. Putting the directive on the child component for that row would be the best way to do this.

When the handle is inside the template of another component, there's no way for cdkDrag to find it since it uses ContentChildren.

@crisbeto This can now be done in Angular with the descendants property in the second argument opts of ContentChildren.

@ContentChildren( DragHandleComponent, { descendants: true } ) dragHandles: QueryList<DragHandleComponent>;

Perhaps an optional CdkDragDeep or CdkDragDescendants directive could be implemented here?

This is what we're doing already: https://github.com/angular/material2/blob/master/src/cdk/drag-drop/directives/drag.ts#L85

Should a cdkDragHandle inside a child component work now @crisbeto ?

From what I can gather it only works when it's a direct descendant, this example looks like the best option that's possible at the moment. https://github.com/angular/material2/pull/13360#issuecomment-463137794

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MurhafSousli picture MurhafSousli  路  3Comments

michaelb-01 picture michaelb-01  路  3Comments

3mp3ri0r picture 3mp3ri0r  路  3Comments

kara picture kara  路  3Comments

dzrust picture dzrust  路  3Comments