Components: Drag Drop Sortable, mixed orientation support

Created on 1 Oct 2018  ·  165Comments  ·  Source: angular/components

Feature request,

Mixed direction support, such as items placed by flex-wrap: wrap

What is the expected behavior?

Should be able to use sortable drag drop on both vertical and horizontal axis at the same time

What is the current behavior?

Only vertical or horizontal is supported

What are the steps to reproduce?

https://stackblitz.com/github/vbwioxyq

Github repo link

https://github.com/abdulkareemnalband/ng-drag-drop/tree/prebuilt-css

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

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/


Angular CLI: 7.0.0-beta.4
Node: 8.11.4
OS: win32 x64
Angular: 7.0.0-rc.0
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, platform-server, router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.9.0-beta.4
@angular-devkit/build-angular     0.9.0-beta.4
@angular-devkit/build-optimizer   0.9.0-beta.4
@angular-devkit/build-webpack     0.9.0-beta.4
@angular-devkit/core              7.0.0-beta.4
@angular-devkit/schematics        7.0.0-beta.4
@angular/cdk                      7.0.0-beta.2
@angular/cli                      7.0.0-beta.4
@angular/flex-layout              6.0.0-beta.16
@angular/material                 7.0.0-beta.2
@ngtools/webpack                  7.0.0-beta.4
@schematics/angular               7.0.0-beta.4
@schematics/update                0.9.0-beta.4
rxjs                              6.3.3
typescript                        3.1.1
webpack                           4.19.1
P2 cddrag-drop feature

Most helpful comment

here is a workaround with using multiple lists
https://stackblitz.com/edit/angular-nuiviw

All 165 comments

@jelbourn hey ,have any progress about this issue now?

Are there any workarounds for drag and drop in mat-grid-list (reordering items in the grid)?

I have an idea, to mark each item in the grid as 'cdkDropList', and handle reordering as dropping item from one cdkDropList to another

  <mat-grid-list [cols]="photoCols"
                       rowHeight="1:1"
                       gutterSize="20px">
          <mat-grid-tile *ngFor="let photo of photos$ | async"
                         cdkDrag
                         cdkDropList
                         (cdkDragEnded)="dragEnded($event)">
            <app-photo-item [Photo]="photo"
                            (OnSelectionChange)="onSelectionChange($event)"></app-photo-item>
          </mat-grid-tile>
</mat-grid-list>

If it will work, I will provide demo

How come the demo gif shows different with what it can provide ? https://cdn-images-1.medium.com/max/800/1*i30ZQdBC7CKbXXdOrUNQcg.gif

@vupham-zingbox +1 , i want to know how to implement what the demo shows

@IhorHolovatsky Nice idea
but only works when no of items in per row is known before hand
But when content reflows on window resize, this is not pretty

Would be nice if what's shown in the demos was actually backed up by the framework code.

Copy and pasting my comment from #13889 since it was a duplicate:

To give an example of the issue, I have a horizontal list of photos that needs to wrap (using fxLayout="row wrap", as the issue description states). However, when it spans multiple lines, it breaks:

drag

Any progress about this issue?

Almost a month has passed , any update now ?

Any progress about this issue?

@MrSnappingTurtle Do you have demo code of multiple list wrap? Thanks :)

Although i know to achieve this feature is very hard. but I still want to ask "any progress about this issue?"

Is there any progress on this one?
Or eventually any idea of when it would be implemented?

This is difficult to implement in the current way it was implemented in the CdkDrag directive. The positioning of the placeholder, and the positions of each item that is clearing way for the placeholder, are done by setting inline CSS transforms to each of the involved elements. This is done in a predictable fashion, meaning that since the dimensions of the dragged element are known from the moment it is dragged, it can be calculated for each of the elements in the list how many pixels they should be shifting back/forth. The calculation is eased further by limiting the transforms to a single axis, allowing the transforms to ignore the widths (or heights in horizontal mode) of elements in the list.

On the other hand, when a list is wrapping, the wrapped elements are being wrapped in an arbitrary manner, calculated by the browser. When so, it is impossible to translate (transform) list elements in a similar predictability, because it is not known (upon drag event) which list elements are wrapping, and where they are positioned relatively within the list.

To circumvent that, upon every drag event, a new snapshot of the list (and all connected lists) must be generated, where the list DOM is being traversed, and each list element gets registered for width and height (practically creating a matrix). Considering that Material devs tried to solve this directive through a performative approach, traversing the DOM and registering each element is not an option as it taxes the browser significantly, and veers from the predictability approach.

Alternatively, a middle ground can be implemented. It is less performative than current solution, but at the same time does not require any heavy calculations. Instead of shifting elements via transform, the placeholder element should be moved (currently it remains in the place of the original dragging element), to be positioned before or after the target drop element. It then could animate the max-height property (or max-width for horizontal). This, as I mentioned, is less performative, but it does allow to shift the placeholder anywhere in the list - even in a wrapping list.

Thank you! I appreciate your help, I'll check it out.

Best regards, Flo

here is a workaround with using multiple lists
https://stackblitz.com/edit/angular-nuiviw

@c3rber That was wonderful! You are my best friend! Thanks a lot ! i will try it.

@c3rber Wow, it's work for me, thx.

But.... Any OFFICIAL progress about this issue? It's for make and standar to this.

Thx

@c3rber Yeah, it is working fine.

Is there a way of animating @c3rber workaround?

@c3rber

Don't work correcty.

If u add a button, for example, for add new items and after reorder the items doesn't work. If you move the ultimate element in tother place don't reorganize correctly

I think that the problem is <div class="example-container" cdkDropListGroup> besacuse @ViewChild(CdkDropListGroup) listGroup: CdkDropListGroup<CdkDropList>; don't update correctly

@NurGuz Check it out. I added an example.
https://stackblitz.com/edit/angular-nuiviw

Placeholder was moved outside the model and also type of data changed from string[][] to items: Array<number> = [1, 2, 3, 4, 5, 6, 7, 8, 9];

@c3rber GJ man! It's okey!

I'm going to try it in my application

I really appreciate your help about this issue, but someting isn't quite
working:

In the Stackblitz demo (https://stackblitz.com/edit/angular-nuiviw)
everything works fine.
I exactly coppied the code into my project and the following happens:

[image: dragdropbug.png]
Sometimes, the wrong item is greyed out. But when releasing the mouse the
dragged item goes to the right place.

It would be really nice if someone can help me out with this!

Thanks, Flo

On Thu, 20 Dec 2018 at 10:22, NurGuz notifications@github.com wrote:

@c3rber https://github.com/c3rber GJ man! It's okey!

I'm going to try it in my application


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/angular/material2/issues/13372#issuecomment-448929235,
or mute the thread
https://github.com/notifications/unsubscribe-auth/Agm6TYSlED1-n9huliaOWscdghRVR9bhks5u61bLgaJpZM4XB1j0
.

@c3rber
Nice solution, although it doesn't work quite well on divs with different width-sizes.
Any solution for this?

@crisbeto This issue should labeled "critical" as most use-cases with responsive design need multi-line support.

@c3rber
Fantastic solution. This is exactly what we were looking for.

Last year , I subscribe this problem , today i hope this problem could be solve in 2019. waiting for it.

Hi all,

If you want that example from @c3rber to work with material grid list (singular), then just change the content of the example container to :

<mat-grid-list
    cdkDropList
    [cdkDropListEnterPredicate]="enter"
    (cdkDropListDropped)="drop()"
    #placeholder
    [gutterSize]="15"
    [cols]="1"
    [rowHeight]="100"></mat-grid-list>

  <mat-grid-list cdkDropList *ngFor="let item of items"
       [cdkDropListEnterPredicate]="enter"
       (cdkDropListDropped)="drop()"
       [gutterSize]="15" [cols]="2" [rowHeight]="100">
    <mat-grid-tile
      cdkDrag
      class="example-box"
      [colspan]="1"
      [rowspan]="2">
      {{item}}
    </mat-grid-tile>
  </mat-grid-list>

and make sure to change the width of example box in the css to :

width: 200px !important;

I'll try and get a demo up over the weekend. Feel free to change columns and rows to see what suits.

I'll be looking further into why this actually works because in my mind, there should be two grid lists and a For loop to create tiles, but in this example, there are many grid lists, one for each tile and then the placeholder as well.

image

Note: obviously, you'd have to also include material package and correct module.

@skatestyle Do you have the same version of the cdk installed as in the demo (7.1.1)?

@devtician Nope, I am currently using 7.2.0

@skatestyle You need to switch to version 7.1.1, because I found that after 7.1.1 some behaviour was changed (not sure what exactly), but this solved it for me.

@devtician even in the demo itself without changing or copying anything over to anywhere else, there is the bug on position 0 when dragging from elsewhere (generally when going diagonally). sometimes it happens, sometimes it doesn't. I've not been able to make it happen when dragging to any other position.

@crisbeto @jelbourn Can you give us any kind of update regarding this issue? I don't think that most of the community or if i speak for myself expect that you give us a timeframe for this feature or that this will be implemented at all. You do amazing work here, but some kind of communication would be helpful. There is no comment from the Angular team on this pretty high discussed issue. I just want to ask you kindly to make communication a little bit more transparent so that we can understand why there is no update since this issue was opened.

@StephenFluin posted on his blog a really good demo: https://stackblitz.com/edit/drag-drop-dashboard
Link to post: https://fluin.io/blog/things-I-wish-I-knew-about-CDK-drag-drop

I've been playing around and it works well, you can achieve some cool things...
My test: https://stackblitz.com/edit/yag-dnd-dashboard

It even works on IE11 👍

A few notes after implementing the workaround:

  • the examples have some extra stuff I didn't need -- at its core, all it does is wrap each item in its own container (ckdDropList), storing the index (in the list) as the data the handler entered uses for rearranging the list
  • sometimes the rearranging action doesn't work (see below)

image

See my Gist for relevant code.

Dragging an item initially from the index 0 to the index 4 as follows: 0 -> 1, 1 -> 2, 2 -> 5, 5 -> 4, the last 5 -> 4 drag does not register.

For now actively telling the (injected) change detector (cd: ChangeDetectorRef) to detect changes as soon as a new ckdDropList works at the cost of firing the handler one extra time each move (0 -> 1, 1 -> 1 instead of just 0 -> 1 for example) as the view updates.

We need this too.

@krusli works perfectly, thank you 👍

@krusli Thx for your solution! Using it with cards, also with animation. Need only some little fixing to work perfect.
One question. You wrote „... some extra stuff I didn't need“. What do you mean with that? Is there a other behaviour to the workaround of c3rber?

@mkarras taking a look at it again, it's just the lack of manually removing and adding HTML elements on the page and notifying the ChangeDetectorRef instead. From the other StackBlitz example it's just the lack of the QueryList stuff.

Functionally they should all be the same/have the same basic idea: get around the problem by using our own data for each cdkDropList and cdkDrag (indices in my example for both cdkDropList and cdkDrag, although you can use different things depending on what you need), then handle the rearranging logic ourselves using said data (calling moveItemsInList or other helpers as needed).

@krusli hey man, but how it will look for this approach?
https://stackoverflow.com/questions/54590576/angular-cdk-drag-and-drop-resize
mb u have an idea..

I'm using dnd2 now. Hope to have the official solution

@qichangjun hm, but it looks like it isn't supported ( https://github.com/akserg/ng2-dnd/issues/274

@kernyden I've only looked at your code a bit so I'm not quite sure about what you're using cdkDrag for. Are you using it to rearrange items, or just to resize the boxes on your page?

@krusli im using cdkDrag for rearrange, grabber and resizable (custom) directives r used for resize.

@kernyden
I probably have dragging problems due to size issues: https://github.com/angular/material2/issues/14093#issuecomment-462395200

In your previous comment you referred to StackOverflow:
https://stackoverflow.com/questions/54590576/angular-cdk-drag-and-drop-resize
However the source is incomplete. Can you please provide the complete source (or better make a StackBlitz, making communication for fixes easier).

This would be nice to have it sorted soon. We also need it.

I have found this incredibly interesting project here: (has no 3rd party dependencies).

https://github.com/swiety85/angular2gridster

DEMO

@yasselavila Your solution worked well for me!

You can save the hassle of using @ViewChildren to get the drop list connections by wrapping the grid list in a cdkDropListGroup:

<div class="wrapper" cdkDropListGroup>
    <mat-grid-list [cols]="responsiveColumns" rowHeight="1:1">
        <mat-grid-tile *ngFor="let item of items; let i = index">
            <cdk-drop-list [cdkDropListData]="i">
                <div cdkDrag (cdkDragDropped)="handleDrop($event)" [cdkDragData]="i">
                    <!-- contents of draggable item -->
                </div>
            </cdk-drop-list>
        </mat-grid-tile>
    </mat-grid-list>
</div>

I have some logic that is called when an item is dropped, so I used cdkDragDropped rather than cdkDragEntered, which would have triggered too many calls.

@spiritintheshiftkey Thank you. Your suggestion helped me reduce some code 👍

Also with CSS columns...
See here https://stackblitz.com/edit/angular-cdk-drag-columns

UPDATE: https://stackblitz.com/edit/angular-cdk-drag-columns-fixed
I got it mostly working with using the cdkDropListGroup. However there is still something a little buggy with it. Interestingly its seems you can have cdkDrag and cdkDropList on the same element also. See my example here. I think most of the same principles will apply to flexbox layout.

If you want to see the buggy-ness, try dragging the first element to the third position then back up in one move... it doesn't let you do it, but if you let go then drag it back up it works.

<div class="container" cdkDropListGroup>

<hello class="item" 
    *ngFor="let item of items; let i = index"
    cdkDropList
    [cdkDropListData]="{ item: item, index: i }" (cdkDropListDropped)="drop($event)"
    cdkDrag
    [name]="item">
    <span cdkDragHandle>= </span>
</hello>

<div *cdkDragPlaceholder></div>

</div>
...
  drop(event: CdkDragDrop<{ item: string, index: number}>) {
    moveItemInArray(this.items, event.previousContainer.data.index, event.container.data.index);
  }

@spiritintheshiftkey I am finding difficulties in implementing cdkDropListGroup with multiple grid-lists. Can you help me if you have a solution for transferring items between grid lists?

@robinprashanth I think the main change from my example above is to handle the dragdata/droplistdata a little differently: you have to make sure that each drag item/drop list pair has a unique number for its data. So if you want to have n grid tiles in each grid list, and generate the grid lists like <mat-grid-list *ngFor="let list of lists; let k = index">, you'd do [cdkDroplistData]="n * k + i" and [cdkDragData]="n * k + i".

I haven't tried keeping each list in a separate array, so I've only tested this with <mat-grid-tile *ngFor="let item of items.slice(n*k, n*(k+1)); let i = index">, but it should be fairly simple to handle separate arrays instead, with some changes to the handleDrop() method.

@spiritintheshiftkey thanks for the help.Let me try.

@crisbeto @devversion @jelbourn
Gentleman, is this issue planned to be fixed this year ?

Sincerely,
Devs.

Nevermind
Best alternative: https://github.com/valor-software/ng2-dragula

Just a thought, make do with vertical list as it is & set the CSS width to make it smaller enough for it to become multi-columns GRID. Would that work better?

here is a workaround with using multiple lists
https://stackblitz.com/edit/angular-nuiviw

I copied and pasted exact code as shared by @c3rber but getting the below error :

Uncaught TypeError: Cannot read property 'children' of null
at CdkDropList.AppComponent.enter [as enterPredicate] (app.component.ts:75)
at DropListRef.CdkDropList._dropListRef.enterPredicate (drag-drop.es5.js:3395)
at DropListRef.push../node_modules/@angular/cdk/esm5/drag-drop.es5.js.DropListRef._canReceive (drag-drop.es5.js:2199)
at drag-drop.es5.js:2176
at Array.find ()
at DropListRef.push../node_modules/@angular/cdk/esm5/drag-drop.es5.js.DropListRef._getSiblingContainerFromPosition (drag-drop.es5.js:2176)
at DragRef.push../node_modules/@angular/cdk/esm5/drag-drop.es5.js.DragRef._updateActiveDropContainer (drag-drop.es5.js:930)
at SafeSubscriber.DragRef._pointerMove [as _next] (drag-drop.es5.js:298)
at SafeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub (Subscriber.js:196)
at SafeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.next (Subscriber.js:134)

Please help.

We need this too.

Hi, just did the code for me to simply log the mouseEnter.
On the drag div, simply added (mouseenter)="enter(index)"

<div fxLayout="row wrap"
     fxLayoutGap="grid"
     fxLayoutAlign="left center"
     cdkDropList
     class="drag-boundary"
     (cdkDropListDropped)="drop($event)">
  <div *ngFor="let item of items; let index = index; trackBy: trackByIndex"
       [style.padding]="'5px'"
       cdkDragBoundary=".drag-boundary"
       cdkDrag
       (mouseenter)="enter(index)">

In the TS:

  drop(event: CdkDragDrop<string[]>) {
    moveItemInArray(you Array, event.previousIndex, this.currentDropIndex);
  }
  enter(index) {
    this.currentDropIndex = index;
  }

Of course this is for a single array to re-order elements

There is still a lot of visual glitch, but at least it's able to re-order properly.
Hope this helps.

Thanks @spiritintheshiftkey! Your soltution did wor well for me (drag and drop across multiple lines)

<div class="wrapper" cdkDropListGroup>
    <mat-grid-list [cols]="responsiveColumns" rowHeight="1:1">
        <mat-grid-tile *ngFor="let item of items; let i = index">
            <cdk-drop-list [cdkDropListData]="i">
                <div cdkDrag (cdkDragDropped)="handleDrop($event)" [cdkDragData]="i">
                    <!-- contents of draggable item -->
                </div>
            </cdk-drop-list>
        </mat-grid-tile>
    </mat-grid-list>
</div>

I have some logic that is called when an item is dropped, so I used cdkDragDropped rather than cdkDragEntered, which would have triggered too many calls.

  public handleDrop(event: CdkDragDrop<any>) {

    const oldPosition = event.item.data;
    const newPosition = event.container.data;

    moveItemInArray(theArray, oldPosition, newPosition);
}

Hi ! Thanks @Francois-Belanger for your solution, it works but visual glitches are annoying
Is there any progress about this issue ?

Hi ! Thanks @Francois-Belanger for your solution, it works but visual glitches are annoying
Is there any progress about this issue ?

Hi, sadly no, I'm waiting for Angular Team to fix this. For my use case it's good enough for now. Hope someone find a better solution.

After losing hope of a fix for this problem, I found this library more suitable and much easier to work with: https://tiberiuzuld.github.io/angular-gridster2/
//-----------------
https://ourcodeworld.com/articles/read/663/top-5-best-draggable-droppable-and-resizable-grid-layout-designer-jquery-and-javascript-plugins

I guess one solution for this can use the drop() method but unfortunately I couldn't make it work. Can someone help what is wrong?

   entered(dragObj: CdkDragEnter) {
        dragObj.container.drop(dragObj.item, dragIndexI, dragElemContainer, false);
    }

so the idea is using GroupList and whenever one item from the first list entered to the other list we manually interchange the places. put the drag item in the second and second in the first. I don't know if this idea works or not but the event trigger before it moves both elements into the same List container, I tried to do it by moving the elements from one container to other but it didn't work properly.

@c3rber thank for your code. I use verson 7.3.7 and in my case the enteredPredicate is called for every all lists not only the one which is entered. so your setup will not work, is this a change in 7.3.7 or bug?
do you have a work around for this?

@tibistibi yes, here is updated code for 7.3.7
https://stackblitz.com/edit/angular-dyz1eb

@c3rber cool.

can you change this: parentNode parentElement to avoid the compile error (node somehow does not have children defined)

@tibistibi yes, here is updated code for 7.3.7
https://stackblitz.com/edit/angular-dyz1eb

You are using CdkDropListContainer which is deprecated and probably in the future will break the code

@tibistibi sure, have changed to parentElement
@aryaroudi thanks, didn't notice. replaced with CdkDropList

@c3rber nice!
there are still some warnings about private methods used. i will look into that (or if you have a solution that would be fine too :)

@c3rber nice!
there are still some warnings about private methods used. i will look into that (or if you have a solution that would be fine too :)

Correct. _getConstrainedPointerPosition or _cacheOwnPosition

those are used to know which is active. i think this can also be done with mouse enter and leave like this:
(mouseenter)="enter(i)" (mouseleave)="leave(i)

so in full it will be this:

  <div cdkDropList id="candidate_list_{{i}}" *ngFor="let item of items; let i = index" (cdkDropListDropped)="drop($event)"
    [cdkDropListEnterPredicate]="enterPredicate" (mouseenter)="enter(i)" (mouseleave)="leave(i)">

@tibistibi yes, but not sure that this will work well on touch screen devices.
I have replaced undocumented private methods with local ones.

great job @c3rber 👍

@c3rber good point, i will investigate and thanks for improving the code!

@c3rber you are right mouseenter did not work on my tablet!

some minor feedback:
to make my strict compiler and formatter happy i needed to do 3 things:
1) change let to const
2) add {} for all if's
3) make functions private methods

and some more:

  1. add implements AfterViewInit
  2. all == and != should be === and !==
  3. " should be '

thanks @c3rber i used your code to create a select candidate page:
https://stackblitz.com/edit/angular-yysvkf

@c3rber Thanks, it works! But there's a minor error in your code, it will not affect ng serve but ng build --prod will have "Expected 0 arguments, but got 1." issue. Here is the issue
In app.component.ts this dropListDropped() method receive no argument
dropListDropped()
But in app.component.html you supply a '$event' into dropListDropped()
<div cdkDropList [cdkDropListEnterPredicate]="dropListEnterPredicate" (cdkDropListDropped)="dropListDropped($event)"></div><div cdkDropList *ngFor="let item of items" [cdkDropListEnterPredicate]="dropListEnterPredicate" (cdkDropListDropped)="dropListDropped($event)">

Just remove $event or add an argument in dropListDropped function.

tldr;
change dropListDropped() to dropListDropped(event)

here is a workaround with using multiple lists
https://stackblitz.com/edit/angular-nuiviw

I copied and pasted exact code as shared by @c3rber but getting the below error :

Uncaught TypeError: Cannot read property 'children' of null
at CdkDropList.AppComponent.enter [as enterPredicate] (app.component.ts:75)
at DropListRef.CdkDropList._dropListRef.enterPredicate (drag-drop.es5.js:3395)
at DropListRef.push../node_modules/@angular/cdk/esm5/drag-drop.es5.js.DropListRef._canReceive (drag-drop.es5.js:2199)
at drag-drop.es5.js:2176
at Array.find ()
at DropListRef.push../node_modules/@angular/cdk/esm5/drag-drop.es5.js.DropListRef._getSiblingContainerFromPosition (drag-drop.es5.js:2176)
at DragRef.push../node_modules/@angular/cdk/esm5/drag-drop.es5.js.DragRef._updateActiveDropContainer (drag-drop.es5.js:930)
at SafeSubscriber.DragRef._pointerMove [as _next] (drag-drop.es5.js:298)
at SafeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub (Subscriber.js:196)
at SafeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.next (Subscriber.js:134)

Please help.

The work around to this is using lesser version of Angular and Angular CDK.

Here's what worked for me,

   "@angular/animations": "7.1.2",
    "@angular/cdk": "7.1.1",
    "@angular/common": "7.0.1",
    "@angular/compiler": "7.0.1",
    "@angular/core": "7.0.1",
    "@angular/forms": "7.0.1",
    "@angular/http": "7.0.1",
    "@angular/platform-browser": "7.0.1",
    "@angular/platform-browser-dynamic": "7.0.1",
    "@angular/platform-server": "7.0.1",
    "@angular/router": "7.0.1",
    "@ng-toolkit/serverless": "7.1.1",
    "@nguniversal/express-engine": "7.1.1"

It doesnot work with above versions of Angular CDK

@tibistibi yes, here is updated code for 7.3.7
https://stackblitz.com/edit/angular-dyz1eb

@cool1nik @amunir9 refer to this latest update that works with @angular/cdk 7.3.7

@tibistibi yes, here is updated code for 7.3.7
https://stackblitz.com/edit/angular-dyz1eb

THANK YOU SO MUCH

Could someone do a npm package for this, so it could easily be integrated ?

I had situation where there is grid items with differing sizes and that caused a lot of not cool behaviour when sorting items on grid. After some fixes to the moveItemInArray indexes it works now in ok level (not perfect at all).

First I went using the solution where cdkDropList directive was used as a child of mat-grid-tile component and sorting is done on cdkDropListEntered event.

<mat-grid-list [cols]="mobileView ? 1 : 2" rowHeight="56px" gutterSize="24px"> <mat-grid-tile *ngFor="let item of grid; trackBy: trackByKey; let i = index;" class="tile" [id]="'grid-item-' + item.key" [colspan]="mobileView ? 1 : item.gridSettings.sizex" [rowspan]="dragOn !== item.key ? item.gridSettings.sizey : (placeholderSizeY || item.gridSettings.sizey)"> <div [class.activedrag]="dragOn === item.key" cdkDropList [cdkDropListConnectedTo]="drops" [cdkDropListData]="i" (cdkDropListEntered)="dropListEnter($event)"></div> </mat-grid-tile> </mat-grid-list>

By using that one starts to get weird problems when dragging items on top of differently sized grid items. So in the dropListEnter function one can correct a bit that behavior:

`dropListEnter($event: CdkDragEnter) {
let indexCorrection: number = 0;

if ($event.container.data > $event.item.data) {
  if (this.grid[$event.item.data]['gridSettings']['sizex'] === 2) {
    // This fill fix situation where one is dragging 2 column chart downwards and chart below is 1 column chart
    if ($event.container.data - $event.item.data === 1
    && this.grid[$event.container.data]['gridSettings']['sizex'] === 1
    && this.grid[$event.container.data + 1]
    && this.grid[$event.container.data + 1]['gridSettings']['sizex'] === 1) {
      indexCorrection--;
    }
  } else {
    // This will fix situation where one is dragging item over 2 column chart
    for (let i = $event.item.data, len = $event.container.data; i < len; i++) {
      if (this.grid[i]['gridSettings'] && this.grid[i]['gridSettings']['sizex'] === 2) {
        indexCorrection++;
      }
    }
  }

  // This will fix situation where one is dragging item downwards when dragged item is bigger than item on right
  if (indexCorrection === 0 && $event.container.data - $event.item.data === 3) {
    const dragEl: HTMLElement = document.getElementById(`grid-item-${ this.grid[$event.item.data]['key'] }`);
    const nextEl: HTMLElement = document.getElementById(`grid-item-${ this.grid[$event.item.data + 1]['key'] }`);

    if ( dragEl && nextEl
        && dragEl.offsetLeft < nextEl.offsetLeft
        && (dragEl.offsetTop + dragEl.offsetHeight) > (nextEl.offsetTop + nextEl.offsetHeight)
    ) {
      indexCorrection++;
    }
  }

  // This will fix situation where one is dragging item downwards when dragged item is bigger than next element
  // and items wouldn't be on their natural places because of item on left is bigger than next element
  if (indexCorrection === 0 && $event.container.data - $event.item.data === 2) {
    const prevLeftEl: HTMLElement = document.getElementById(
      `grid-item-${ this.grid[$event.item.data - 1]['key'] }`
    );
    const dragEl: HTMLElement = document.getElementById(`grid-item-${ this.grid[$event.item.data]['key'] }`);
    const nextEl: HTMLElement = document.getElementById(`grid-item-${ this.grid[$event.item.data + 1]['key'] }`);

    if ( prevLeftEl && dragEl && nextEl
        && dragEl.offsetLeft > nextEl.offsetLeft
        && (prevLeftEl.offsetTop + prevLeftEl.offsetHeight) > (dragEl.offsetTop + nextEl.offsetHeight)
    ) {
      indexCorrection++;
    }
  }
}

// This will fix situation where one is dragging item upwards when dragged item is smaller than target element
// and thus mouse cursor would end up on top of wrong element
if (
  $event.container.data < $event.item.data &&
  this.grid[$event.container.data]['gridSettings']['sizey'] > this.grid[$event.item.data]['gridSettings']['sizey']
) {
  const dragEl: HTMLElement = document.getElementById(`grid-item-${ this.grid[$event.item.data]['key'] }`);
  const targetEl: HTMLElement = document.getElementById(`grid-item-${ this.grid[$event.container.data]['key'] }`);

  if ( dragEl.offsetTop > targetEl.offsetTop) {
    this.placeholderSizeY = this.grid[$event.container.data]['gridSettings']['sizey'];
  } else {
    this.placeholderSizeY = null;
  }
} else if ($event.container.data === $event.item.data) {

} else {
  this.placeholderSizeY = null;
}

// I made custom move item in array function but idea is like moveItemInArray(grid, previousIndex, newIndex - indexCorrection)
moveItemInArray(this.grid, this.grid[$event.item.data], this.grid[$event.container.data - indexCorrection]);

this.cdRef.markForCheck();
this.cdRef.detectChanges();

}`

Hopefully this helps if someone is working with 2 column grid where grid items have differing sizes.

I really hope that mat-grid-list and cdk-drag-drop would have some kind of official relationship in the future so that one doesn't have to use forced marriage between them.

@crisbeto will this bug be fixed in next release of CDK, planned for Q1 → Q2 2019 (January - June)?

@masaala please post a stackblitz.
@seriojak its not a bug, its just a very important feature that hasnt been covered yet.

We definitely plan on doing this at some point, but it's actually quite a difficult feature to implement. We don't currently have an ETA on this. If someone would like to contribute something here, please follow the process outlined in our contributing guide and start a discussion before committing to any code.

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

This works also with angular material 8. Thanks

@tibistibi yes, here is updated code for 7.3.7
https://stackblitz.com/edit/angular-dyz1eb

Cool

@tibistibi yes, here is updated code for 7.3.7
https://stackblitz.com/edit/angular-dyz1eb

Thanks a lot!

Is there any official solution to make it with mat-grid-list??

Can we add a critical label on this issue as it is one of the most requested features?

@tibistibi yes, here is updated code for 7.3.7
https://stackblitz.com/edit/angular-dyz1eb

I created a dynamic component based on this stackblitz example.
https://github.com/sam-1994/ngx-drag-and-drop-grid

Currently it is only tested with Angular 8.x.
Feel free to include it in your projects or giving feedback for improvements

@c3rber what is the license for your code in https://stackblitz.com/edit/angular-dyz1eb ?

It is so good that I wanted to copy, modify and use this code, but not sure if it is legal. :-)

Hi everyone,
i would like to share my solution for the mixed orientation problem, here are the steps:
1- just put the cdkDropList as always:
<div class="container" cdkDropList (cdkDropListDropped) = "drop($event)" cdkDropListOrientation="horizontal">
2- on the draggable element we r going to create a directive with a hostlistner :
<div cdkDrag appDropzone (received)="onDrop(elementcdkDrag)" >
3- on component.ts we create our onDrop method, to store the data in a variable called 'droppedOn':
onDrop(elementcdkDrag: any) { console.log('droopedon', elementcdkDrag); this.droppedOn = elementcdkDrag; }
4- we override the drop method:
drop(event: CdkDragDrop<any[]>) { const elementsToExchange: any[] = [this.yourArray[event.previousIndex].id, this.droppedOn.id]; if (elementsToExchange[0].id !== elementsToExchange[1].id) { // i rerender my grid here } }
5- finally here is my hostListhner:
@Directive({ selector: '[appDropzone]' }) export class DropzoneDirective { @Output() received = new EventEmitter<element>(); constructor() { } @HostListener('mouseenter', ['$event']) onDrop($event) { $event.preventDefault(); this.received.emit($event.element); } }

hope it's useful

I have the same problem with chip-list https://stackblitz.com/edit/angular-chips-pfmtqy
The implementation its from angular/material examples with CdkDragDrop but its only for horizontal orientation. So if you have more than 1 line chips you cant drag n drop.

@tibistibi yes, here is updated code for 7.3.7
https://stackblitz.com/edit/angular-dyz1eb

I created a dynamic component based on this stackblitz example.
https://github.com/sam-1994/ngx-drag-and-drop-grid

Currently it is only tested with Angular 8.x.
Feel free to include it in your projects or giving feedback for improvements

I'm having problem with https://stackblitz.com/edit/angular-dyz1eb when i use ngIf to dynamically display 2 different list, but when i try to drag drop, the dropElement index in the dropElement list seems to increase. The bug only happen once each time i show different view.
Your component seems to fix that issue, may i ask what exactly did you do to fix it? i'm investigating your code but can't find anything
My issue is presented in this: https://stackblitz.com/edit/angular-yq6dww

@sam-1994

@tibistibi yes, here is updated code for 7.3.7
https://stackblitz.com/edit/angular-dyz1eb

I created a dynamic component based on this stackblitz example.
https://github.com/sam-1994/ngx-drag-and-drop-grid

Currently it is only tested with Angular 8.x.
Feel free to include it in your projects or giving feedback for improvements

Hi Sam and thanks for your work;
YOur solution is the only one working for me over Angular 8.
can you please tell me which event we can use (similar to (cdkDropListDropped) ) because it s not written in the API.

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

This works also with angular material 8. Thanks

and some more:

  1. add implements AfterViewInit
  2. all == and != should be === and !==
  3. " should be '

thanks @c3rber i used your code to create a select candidate page:
https://stackblitz.com/edit/angular-yysvkf

@c3rber
How can we implement drag drop with multiple lists which have flex-wrap: wrap
In the above example moving items from Matched to Kandidaten list

ck for improv

@tibistibi yes, here is updated code for 7.3.7
https://stackblitz.com/edit/angular-dyz1eb

I created a dynamic component based on this stackblitz example.
https://github.com/sam-1994/ngx-drag-and-drop-grid

Currently it is only tested with Angular 8.x.
Feel free to include it in your projects or giving feedback for improvements

Hey Sam how to have multiple sam-drag-and-drop-grid and drag between them

I know this issue is one year old but I need this feature, too 😅

Seeing as this probably isn't going to be resolved soon, I've been using dragula which works for this particular use case. Happy with it so far.

Seeing as this probably isn't going to be resolved soon, I've been using dragula which works for this particular use case. Happy with it so far.

@BovineEnthusiast thank you very much! Because I only used the Drag&Drop fetaure from cdk, I replaced it now with dragula. After a short time I finally implemented the drag&drop behaviour as I planned. Dragula is what I was looking for!

DragDropGif

Yeah Dragula is straight forward, but it's not been updated since an year, my team is looking for a solution with angular material

I have implemented another simple solution using Angular's toolkit (cdkDropListGroup, moveItemInArray, and transferArrayItem): https://stackblitz.com/edit/angular-drag-n-drop-mixed-orientation-example
Basically the idea is mapping a one-dimensional list (represented by the input model) into a two-dimensional items table matrix (view model representing the flex row wrap). I have posted a detailed explanation here: https://taitruong.github.io/software-developer.org/post/2019/10/26/Angular-drag'n'drop-mixed-orientation-in-flex-row-wrap/

Seeing as this probably isn't going to be resolved soon, I've been using dragula which works for this particular use case. Happy with it so far.

@BovineEnthusiast thank you very much! Because I only used the Drag&Drop fetaure from cdk, I replaced it now with dragula. After a short time I finally implemented the drag&drop behaviour as I planned. Dragula is what I was looking for!

DragDropGif

do you have a demo with this example?

@joseph118
I'm currently using another implementation (third iteration), where I use a dragable table that allows to drag & drop its columns. The second iteration is similar to the animation:
2019-11-01 22-25-10 2019-11-01 22_28_55

I don't have a real demo to this, but you can have a look on the code in my repository:
https://github.com/IPS-LMU/octra/tree/43c2d0a4dfed3beb7636ef57ad9b3582b24066b3/src/app/core/component/table-configurator

I have implemented another simple solution using Angular's toolkit (cdkDropListGroup, moveItemInArray, and transferArrayItem): https://stackblitz.com/edit/angular-drag-n-drop-mixed-orientation-example
Basically the idea is mapping a one-dimensional list (represented by the input model) into a two-dimensional items table matrix (view model representing the flex row wrap). I have posted a detailed explanation here: https://taitruong.github.io/software-developer.org/post/2019/10/26/Angular-drag'n'drop-mixed-orientation-in-flex-row-wrap/

no manipulation with DOM. perfectly!! Thanks

Bumping this issue as well, it would be very nice to have native drag support

Hi there, also waiting for this feature to be onboarded. Any plans on integrating this for ng9 ?

Really need this feature and don't want to use hacky workaround

Any roadmap for the cdk? Supporting flex-box or wrapped row is really important

@tibistibi yes, here is updated code for 7.3.7
https://stackblitz.com/edit/angular-dyz1eb

@c3rber @tibistibi thank you very much! Basically the window should scroll when the user approaches the viewport edge while dragging an element; which is not happening in this solution. Is there any workaround for this (cdk version: 7.2.X)?

@taitruong nice, thanks for the comprehensive writeup. Do you suspect this would/wouldn't work with a masonry style layout? I'm struggling to wrap my head around any potential pitfalls before I go headlong into trying to get something like this working!

@taitruong nice, thanks for the comprehensive writeup. Do you suspect this would/wouldn't work with a masonry style layout? I'm struggling to wrap my head around any potential pitfalls before I go headlong into trying to get something like this working!

Send me a stackblitz example and I'll have a look at it.

@tibistibi yes, here is updated code for 7.3.7
https://stackblitz.com/edit/angular-dyz1eb

@c3rber @tibistibi thank you very much! Basically the window should scroll when the user approaches the viewport edge while dragging an element; which is not happening in this solution. Is there any workaround for this (cdk version: 7.2.X)?

Got a work around for this, in @c3rber 's solution;

dragMoved(e: CdkDragMove) {
if (e.delta.y === 1) {
this.scrollContainer.nativeElement.scrollTop += 3;
} else {
this.scrollContainer.nativeElement.scrollTop -= 3;
}

where scrollContainer is the outer container in which cdkDropListGroup is assigned.

What is official dev's position? Will they fix it or not? We are in process of migrating jquery-ui-draggable and lacking this feature is a roadblock for killing jquery-ui in our product.

This is high on our backlog- we're considering this for scheduling in Q1 2020, but it's competing with a few other big-ticket items (date-range picker, virtual-scroll in table, and a few others)

Is this going to be fixed / added by any chance?

We decided to go with adding a date-range-picker for Q1 2020, but this is still high on the backlog priority list.

Having same issue. I reproduced this issue in Angular Demo.
Check Demo

@tibistibi yes, here is updated code for 7.3.7
https://stackblitz.com/edit/angular-dyz1eb

I've created something based on this solution that swaps positions when dropping, thought I'd share it if anyone needs this sort of thing:
https://stackblitz.com/edit/angular-cdkdroplist-wrap-replaceondrop

I had trouble implementing drag and drop with mixed-orientation support with the CDK. Additionally to the mixed-orientation behavior, I also needed to be able to select multiple items at a time.

Therefore I went one and built a new library called ng-sortgrid which allows you to drag multiple or single items at the same time in mixed directions. Maybe it's helpful to somebody.

GitHub: https://github.com/kreuzerk/ng-sortgrid
NPM: https://www.npmjs.com/package/ng-sortgrid

@kreuzerk very brave to give it a try. Its one of the more challenging things to implement. I looked at it. Look very promising. I filed a few issues :P .

We decided to go with adding a date-range-picker for Q1 2020, but this is still high on the backlog priority list.

This is really kind of a deal-breaker in an otherwise great feature. I was puzzled to see the misbehavior once the elements spawned across two rows. Waiting to test this in beta,

it's been almost 2 years and this feature is missing, are there any plans to release it or should I look for other libraries? can you recommande any alternative please?
Thanks

it's been almost 2 years and this feature is missing, are there any plans to release it or should I look for other libraries? can you recommande any alternative please?
Thanks

I think it's better to use ng2-dragula. It's much easier to make mix orientation, but it doesn't support dragging 1 panel inside browser window, only inside/between two list

@Polarts your solution works best from my testing however the drop animation seems to transition to the wrong element on occasion. Your Stackblitz demo shows the same behavior. Any idea how this could be fixed?

Here's a video of the issue: https://youtu.be/mi5gKV8CD9w

I found this ng2 dragula to get the job done (Drag and drop so simple it hurts) :D

Demo

See -> https://stackoverflow.com/questions/51360466/how-to-drag-and-reorder-content-in-angular

It' s a shame that i cannot use Angular' s official package because of not supporting mixed direction. And this bug is alive for 2 years...

I' ll go and try ngx-drag-drop which mentioned above. Seems it has a various support for move, copy etc. operations.

Guys, this is an open-source project and even if it is backed by Google, still they might have a lot of other priorities. Let's try to show some empathy to the team and wait for them to fix it. If this something a beginner OS maintainer can pick up and fix it might have happened already.

Is it a bad thing to wanting support for mixed direction support? I don' t understand why i had so much downvote for the request.

While i' m saying "it' s a shame", i don' t try to mean anybody, i just want to show my disappointment, sadness because this request is alive for 2 years.

There' re many alternatives for drag & drop which supports mixed direction, but if i' ve a choice, i want to use offical cdk.

Is it a bad thing to wanting support for mixed direction support? I don't understand why i had so much downvote for the request.

Not sure why people are down voting. If I had to guess it was due to you saying this is a bug, when its a feature.

I personally would use another drag and drop lib in the mean time if the current cdk doesn't meet your current requirements.

Drag and drop isn't simple, isn't used in a lot of apps, and requires a lot of work to add more complex features so it makes sense this is stuck in the backlog. I personally was surprised DnD was added to the CDK at all since it can (and has been) a Pandora's box of "I need more DnD features!".

If anything, having the feature stuck in a backlog as "high" is vastly better then the feature being labeled as "not going to fix", or for the maintainers to drop off the face of the earth.

While i' m saying "it' s a shame", i don' t try to mean anybody, i just want to show my disappointment, sadness because this request is alive for 2 years.

I understand your intention may not be to hurt anyone, but when we are not discussing face to face and only using text as a communication medium, the text is open to interpretation. I can think of it that you're being mean and putting the maintainers on blame for not taking your issues as their high priority.

I am not saying that you did that, but it is just open to interpretation, so please think of better choice of words to let others know of your frustration and need for the feature.

Hi,
All those examples and workarounds are working with same-size items as i understood.
Did someone found for masonry layout for mutlidirection movements solution?
For me fits best this solution https://stackblitz.com/edit/angular-nuiviw
but of course not perfect (anyway thanks athour for best example) - problem with placeholder correct placement during drop.
Used:
1) flex column wrap
2) dynamic height calculation (with some extra empty space below)
3) nth-of-type-of for placing elements in row like view - this article was very helpfull - https://tobiasahlin.com/blog/masonry-with-css/#the-solution

And wating for native Angular functionality :)

Hello,

I have been using @c3rber solution https://stackblitz.com/edit/angular-nuiviw for a long time now, but I saw that the method being used to diplay the placeholder CdkDropList::enter(item: CdkDrag, pointerX: number, pointerY: number): void; is now deprecated in Angular 9, which means that in Angular 10, @c3rber's solution will no longer work...

Since it is the only solution I found that is using exclusively Angular Material to achieve drag & drop with mixed orientation support, it sounds like a very bad news, to me at least.

This is high on our backlog- we're considering this for scheduling in Q1 2020, but it's competing with a few other big-ticket items (date-range picker, virtual-scroll in table, and a few others)

@jelbourn Do you think drag & drop with mixed orientation support will be ready for Angular 10 ?

We've since switched to use ng2-dragula instead of CDK. This

  1. Reduced the amount of code required - especially the workarounds are a lot of code.
  2. Reduced the complexity of the code required - same thing.
  3. Looks exactly the same to the user - except that it works properly :)

Yes please! ...and thank you to @oleggd for the workaround. I did notice that two methods in your work will be removed in Angular 10. The team says they are no longer in use but if you remove them, it does change the animation.

this.source.start();
    this.placeholder.enter(drag, drag.element.nativeElement.offsetLeft, drag.element.nativeElement.offsetTop);

Yes please! ...and thank you to @oleggd for the workaround. I did notice that two methods in your work will be removed in Angular 10. The team says they are no longer in use but if you remove them, it does change the animation.

this.source.start();
    this.placeholder.enter(drag, drag.element.nativeElement.offsetLeft, drag.element.nativeElement.offsetTop);

Hi Bjorn,

i decided to move in from deprecated enter to this way (will repeat first part):
0) i have items (1,2,3,4,5) with different sizes
1) using flex + column direction to make possible have masonry in each column with flex
2) using order nth-of-type + order to place items in horisontal order, i.e.
flex+column will give you columns like
1 | 4| 6|
2 | 5| 7|
3| |8|
with order (as in article- see url above
1|2|3|
4|5|6|
7|8|
3) i'm calculation manually exact height of max columns by size of items and columns count for existing screen size (width) and setting for screen
4) and
on cdkDrag:

  • onDragStarted(event) - saving drag element info - not removing it from whole item list - this allow to have "snake" the same without reorder
  • onDragEntered(event) - saving target and applying opacity to show place where you can drop
    on cdkDropList:
  • onDropCard - and you will drop - moveItemInArray, reorder source item list and, clear source and target
    This saving me from reordering of "snake" items (or how to call it :) items snake) - because it's very hard to see and remeber and understand from where you've took your card and where you want to put it :) when card moved and have different size.
    so, no extraplaceholder for saving item, no switch items each time when item over drop zone, no reordering (for my case it's a problem)

@oleggd Do you have an updated code sample of this? Almost sounds like you should create your own Angular module and make it available to the community 👏🏻

Hi Bjorn,
no, only app worked code :) - so can't put it here, will try to do some sketch or something on stackblitz maybe this week.

The best working solution for me is https://sortablejs.github.io/Sortable/
Here is implementation of this library for Angular https://www.npmjs.com/package/ngx-sortable

ezgif-4-b9d07a58b6b9

Dude! Thank you for mentioning sortablejs. Its acutally sick.

stackblitz editor
stackblitz fullscreen demo

  • nesting
  • works in css grid (mixed-direction)
  • there is a multiselect plugin
  • draggin between container

Hi oleksiv,
i have different sized items and they are placed verticaly - masonry and when card placed in some possible drop position this resorting just breaking eyes :)

Bjorn, i did some sketch ( but broke something (html + css) when tried to cleanup and reduce all odd components in html - not refreshing clearly after drop) - not sure that it's good example but you can check at least an idea.
https://stackblitz.com/edit/angular-ya7kh6
Maybe you can comment some bad points.
forgot to tell - colors showing column order, numbers before card - order in array.

I came up with a workaround of differently sized boxes in a CSS grid, based on @c3rber 's solution.

https://stackblitz.com/edit/angular-47mw46

I came up with a workaround of differently sized boxes in a CSS grid, based on @c3rber 's solution.

https://stackblitz.com/edit/angular-47mw46

Could you share an updated workaround working with the last 10 release? Thanks

I came up with a workaround of differently sized boxes in a CSS grid, based on @c3rber 's solution.
https://stackblitz.com/edit/angular-47mw46

Could you share an updated workaround working with the last 10 release? Thanks

Here you go:
https://stackblitz.com/edit/angular-hp5zkg

I came up with a workaround of differently sized boxes in a CSS grid, based on @c3rber 's solution.
https://stackblitz.com/edit/angular-47mw46

Could you share an updated workaround working with the last 10 release? Thanks

Here you go:
https://stackblitz.com/edit/angular-hp5zkg

You rock! Thanks very much!

Another solution is ng-sortgrid by @kreuzerk . It supports multiple selection for drag/drop which I happened to need.
https://github.com/kreuzerk/ng-sortgrid#readme

Another solution is ng-sortgrid by @kreuzerk . It supports multiple selection for drag/drop which I happened to need.
https://github.com/kreuzerk/ng-sortgrid#readme

Played around a bit, but it doesn't seem to work when placed in a shadow root.

Solved the task with https://github.com/SortableJS/ngx-sortablejs

Hi;

If you use draggable property be aware that there' s a bug in the latest version (v3.1.4). I' ve created issue about the bug: https://github.com/SortableJS/ngx-sortablejs/issues/202

It' s working ok with v3.1.3.

It' s sad that owner of the ngx-sortablejs is looking for a maintainer.

Is there any progress on this one?
Or eventually any idea of when it would be implemented?

I tried this solution and it works for me !!
The problem with cdk drag is the previousIndex & the currentIndex : in case there's more than one raw they give the wrong position.
In this example we set CdkDrag for every item and we keep his position; after that you can change drop() method:
Stackoverflow task :https://stackoverflow.com/questions/60315566/angular-material-drag-and-drop-multi-row-list
example: https://stackblitz.com/edit/angular-mzavwv?file=src%2Fapp%2Fapp.component.ts

Is there any progress on this one?
Or eventually any idea of when it would be implemented?

You can try my proposal, still working for my case
https://stackblitz.com/edit/angular-ya7kh6

@oleggd Thanks but I needed it to be with css grid instead of flex, in the end I have made a base with js and event listeners
https://github.com/nabby27/drag-drop-grid

Thanks for the good workaround with the custom implementation of the drop and enter behavior.

Is the workaround possible to support a transfer between different lists?

I ended up using the Kendo Sortable (be aware that you need to buy a license though).

I came up with a workaround of differently sized boxes in a CSS grid, based on @c3rber 's solution.
https://stackblitz.com/edit/angular-47mw46

Could you share an updated workaround working with the last 10 release? Thanks

Here you go:
https://stackblitz.com/edit/angular-hp5zkg

Thanks!

You had an issue when dragging item forward.
You can reproduce it by using only small items (like 1, 3, 5).
try to do that: 1 3 5 => 3 1 5 => 1 3 5
sometime the item will jump extra tile forward.

This code include my fix. I've used the placeholder element as the target:
https://stackblitz.com/edit/angular-w3cdky

I came up with a workaround of differently sized boxes in a CSS grid, based on @c3rber 's solution.
https://stackblitz.com/edit/angular-47mw46

Could you share an updated workaround working with the last 10 release? Thanks

Here you go:
https://stackblitz.com/edit/angular-hp5zkg

Thanks!

You had an issue when dragging item forward.
You can reproduce it by using only small items (like 1, 3, 5).
try to do that: 1 3 5 => 3 1 5 => 1 3 5
sometime the item will jump extra tile forward.

This code include my fix. I've used the placeholder element as the target:
https://stackblitz.com/edit/angular-w3cdky

Thank you very much!

I came up with a workaround of differently sized boxes in a CSS grid, based on @c3rber 's solution.
https://stackblitz.com/edit/angular-47mw46

Could you share an updated workaround working with the last 10 release? Thanks

Here you go:
https://stackblitz.com/edit/angular-hp5zkg

Thanks!

You had an issue when dragging item forward.
You can reproduce it by using only small items (like 1, 3, 5).
try to do that: 1 3 5 => 3 1 5 => 1 3 5
sometime the item will jump extra tile forward.

This code include my fix. I've used the placeholder element as the target:
https://stackblitz.com/edit/angular-w3cdky

I get errors when running this with latest Angular 11 version... have you tried with that? See below:

line 127 on app.component.ts (referred in the error output) is:

this.source._dropListRef.start();

zone-evergreen.js:171 Uncaught RangeError: Maximum call stack size exceeded
at SafeSubscriber.unsubscribe (Subscription.js:41)
at SafeSubscriber.unsubscribe (Subscriber.js:69)
at SafeSubscriber.__tryOrUnsub (Subscriber.js:186)
at SafeSubscriber.next (Subscriber.js:122)
at Subscriber._next (Subscriber.js:72)
at Subscriber.next (Subscriber.js:49)
at Subject.next (Subject.js:39)
at DropListRef._draggingStarted (drag-drop.js:1845)
at DropListRef.start (drag-drop.js:1540)
at CdkDropList.AppComponent.enter [as enterPredicate] (app.component.ts:127)
runTask @ zone-evergreen.js:171
invokeTask @ zone-evergreen.js:480
ZoneTask.invoke @ zone-evergreen.js:469
timer @ zone-evergreen.js:2552
setTimeout (async)
scheduleTask @ zone-evergreen.js:2573
scheduleTask @ zone-evergreen.js:385
scheduleTask @ zone-evergreen.js:210
scheduleMacroTask @ zone-evergreen.js:233
scheduleMacroTaskWithCurrentZone @ zone-evergreen.js:1134
(anonymous) @ zone-evergreen.js:2586
proto. @ zone-evergreen.js:1449
hostReportError @ hostReportError.js:2
__tryOrUnsub @ Subscriber.js:191
next @ Subscriber.js:122
_next @ Subscriber.js:72
next @ Subscriber.js:49
next @ Subject.js:39
handler @ drag-drop.js:2382
invokeTask @ zone-evergreen.js:399
runTask @ zone-evergreen.js:167
invokeTask @ zone-evergreen.js:480
invokeTask @ zone-evergreen.js:1621
globalZoneAwareCaptureCallback @ zone-evergreen.js:1679
core.js:5980 ERROR TypeError: Cannot read property 'data' of undefined
at SafeSubscriber._next (drag-drop.js:3400)
at SafeSubscriber.__tryOrUnsub (Subscriber.js:183)
at SafeSubscriber.next (Subscriber.js:122)
at Subscriber._next (Subscriber.js:72)
at Subscriber.next (Subscriber.js:49)
at Subject.next (Subject.js:39)
at drag-drop.js:873
at ZoneDelegate.invoke (zone-evergreen.js:364)
at Object.onInvoke (core.js:28301)
at ZoneDelegate.invoke (zone-evergreen.js:363)
defaultErrorLogger @ core.js:5980
handleError @ core.js:6028
next @ core.js:28901
schedulerFn @ core.js:25666
__tryOrUnsub @ Subscriber.js:183
next @ Subscriber.js:122
_next @ Subscriber.js:72
next @ Subscriber.js:49
next @ Subject.js:39
emit @ core.js:25656
(anonymous) @ core.js:28324
invoke @ zone-evergreen.js:364
run @ zone-evergreen.js:123
runOutsideAngular @ core.js:28229
onHandleError @ core.js:28324
handleError @ zone-evergreen.js:368
runTask @ zone-evergreen.js:170
invokeTask @ zone-evergreen.js:480
ZoneTask.invoke @ zone-evergreen.js:469
timer @ zone-evergreen.js:2552
setTimeout (async)
scheduleTask @ zone-evergreen.js:2573
scheduleTask @ zone-evergreen.js:385
onScheduleTask @ zone-evergreen.js:272
scheduleTask @ zone-evergreen.js:378
scheduleTask @ zone-evergreen.js:210
scheduleMacroTask @ zone-evergreen.js:233
scheduleMacroTaskWithCurrentZone @ zone-evergreen.js:1134
(anonymous) @ zone-evergreen.js:2586
proto. @ zone-evergreen.js:1449
hostReportError @ hostReportError.js:2
__tryOrUnsub @ Subscriber.js:191
next @ Subscriber.js:122
_next @ Subscriber.js:72
next @ Subscriber.js:49
next @ Subject.js:39
(anonymous) @ drag-drop.js:873
invoke @ zone-evergreen.js:364
onInvoke @ core.js:28301
invoke @ zone-evergreen.js:363
run @ zone-evergreen.js:123
run @ core.js:28184
_cleanupDragArtifacts @ drag-drop.js:866
(anonymous) @ drag-drop.js:733
invoke @ zone-evergreen.js:364
run @ zone-evergreen.js:123
(anonymous) @ zone-evergreen.js:857
invokeTask @ zone-evergreen.js:399
runTask @ zone-evergreen.js:167
drainMicroTaskQueue @ zone-evergreen.js:569
invokeTask @ zone-evergreen.js:484
invokeTask @ zone-evergreen.js:1621
globalZoneAwareCaptureCallback @ zone-evergreen.js:1679
Show 22 more frames
core.js:5980 ERROR TypeError: Cannot read property 'data' of undefined
at SafeSubscriber._next (drag-drop.js:2811)
at SafeSubscriber.__tryOrUnsub (Subscriber.js:183)
at SafeSubscriber.next (Subscriber.js:122)
at Subscriber._next (Subscriber.js:72)
at Subscriber.next (Subscriber.js:49)
at Subject.next (Subject.js:39)
at DropListRef.drop (drag-drop.js:1628)
at drag-drop.js:882
at ZoneDelegate.invoke (zone-evergreen.js:364)
at Object.onInvoke (core.js:28301)

indeed, seems like the solution is broken with Angular 11

Have any solution for Angular 11?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alanpurple picture alanpurple  ·  3Comments

Hiblton picture Hiblton  ·  3Comments

michaelb-01 picture michaelb-01  ·  3Comments

Miiekeee picture Miiekeee  ·  3Comments

julianobrasil picture julianobrasil  ·  3Comments