reppners / ngx-drag-drop

Angular directives using the native HTML Drag And Drop API
https://reppners.github.io/ngx-drag-drop/
BSD 3-Clause "New" or "Revised" License
307 stars 120 forks source link

how to implement 'snap-to' drop #99

Open grimace opened 2 years ago

grimace commented 2 years ago

I'm try to drop onto view where the drop should only be allowed along grid lines (or grid spacing). The view is large and so seems like it wouldn't work as dropList. I haven't found this in the docs. How could this be accomplished?

reppners commented 2 years ago

Maybe https://github.com/tiberiuzuld/angular-gridster2 is a good fit for your requirements. Another way to tackle it would be separate dropzones, each dropzone resembling a row or column. Also check out https://material.angular.io/cdk/drag-drop/overview#restricting-movement-along-an-axis.

reppners commented 2 years ago

How is your grid achieved? Do you use css grid-layout? To get a result as you are describing, at least with this module (or any other html5 drag and drop) there needs to be an element that acts as a dropzone and then is styled/sized with css as needed.

So if only dropping on grid spacing / lines is allowed, this needs to be reflected in the DOM hierarchy if you're wanting to use a declarative approach. That means many small dropzones located at the spacing/lines.

Another - more custom - approach would be, that the dropzone is the container element of the grid and the styling happens based on the drag events emitted by dragging an element over the grid (dragover, https://developer.mozilla.org/en-US/docs/Web/API/Document/dragover_event). Then use the dragover-coordinates and hit-testing (https://developer.mozilla.org/en-US/docs/Web/API/Document/elementFromPoint) to find out if you're hovering over a grid-line/grid-space (thats the hard part I guess.. dunno if possible with every way of creating a grid with html/css) and adjust styling, allow/deny the drop based on that.

mennolodder commented 2 years ago

Would it be possible to achieve this using typescript code to set the location of the dragged element? For instance to implement a X or Y only drag?

Is there a (clean) way to override this when getting the drag event? (how does angular material do that?)

For some use cases, another way might be to have a placeholder on the snapping point, and when the dragged element gets close you hide the dragged element and only show the placeholder. (not sure yet how you'd cleanly detect getting close though)