angular material drag and drop triggers a callback once the css transition has completed

I have successfully implemented a list of elements that can be dragged and dropped using Angular Material's drag and drop feature, similar to the tutorial available at this link.

In my implementation, I have a "drop(event)" function that not only moves elements in the Angular model but also sends a request to the server and updates the model when a response is received. However, an issue arises where there is a noticeable jumping of elements because the Angular model is not changed immediately when dropping an element – it jumps back to its original position before moving to the new position once the server response is processed.

To make this process smoother for users, I want to somehow conceal the background work happening during the update.

  1. One solution could be to maintain two separate lists – one for the user interface and another for the server – and update them accordingly (the user list upon drop and the server list upon response), but this approach may be difficult to manage.

I am exploring the idea of using CSS animations to address the issue. The drag and drop example already demonstrates the use of:

.cdk-drag-animating {
  transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}

The 'transition: transform' property provides a smooth animation when an element is dropped. My aim is to show users a 0.5-second animation, which should provide ample time for the server response to update the model before the animation completes.

However, I noticed that the 'drop($event)' function is called after the transition ends, regardless of the duration set for the transition. This behavior seems unexpected to me as I assumed the function would be triggered upon releasing the mouse. Any insights on how to handle hiding the model update and resolving the issue with the CSS animation transitions?

Update: I have created an example showcasing the problem mentioned above. Click here to view the example.

Answer №1

After the transition has ended, the drop function is called. This means that even if I set a 2000ms transform, the drop function will still be executed after the transition ends, which is after 2 seconds. Is this the expected behavior? I was under the impression that the function should be triggered upon releasing the mouse.

Yes, this behavior is expected due to technical reasons. The cdkDrag functionality creates a copy of the dragged element and adjusts the positions of other items using position fixed. Once the dragging action is completed (mouse up), the animation kicks in. Only after the animation completes does Angular reposition the items for a smooth transition. If this step is skipped, the elements would abruptly return to their original order before transitioning to the new order.

If you want the function to be called just before the animation ends, you can utilize cdkDragReleased. This event fires right before the animation completion. You can see the updated StackBlitz example here.

For additional information such as container details, index, or item specifics, refer to events like cdkDragExited and cdkDragEntered. Explore more in the official documentation.

Demo:

<div cdkDropListGroup>
  <div class="example-container">
    <h2>Available items</h2>

    <div
      cdkDropList
      id="test"
      [cdkDropListData]="items"
      class="example-list"
      cdkDropListSortingDisabled
      (cdkDropListDropped)="drop($event)"
>
      <div class="example-box" *ngFor="let item of items" (cdkDragEntered)="cdkDropListEntered($event)"
      (cdkDragExited)="cdkDropListExited($event)" (cdkDragReleased)="dragEnd($event)" cdkDrag>{{item}}</div>
    </div>
  </div>

  <div class="example-container">
    <h2>Shopping basket</h2>

    <div
    id="super"
      cdkDropList
      [cdkDropListData]="basket"
      class="example-list"
      (cdkDropListDropped)="drop($event)"
      >
      <div class="example-box" *ngFor="let item of basket" (cdkDragEntered)="cdkDropListEntered($event)"
      (cdkDragExited)="cdkDropListExited($event)" (cdkDragReleased)="dragEnd($event)" cdkDrag>{{item}}</div>
    </div>
  </div>
</div>

Code

dragEnd(event: any) {
    console.log('End', event);
  }

  cdkDropListEntered(event: any) {
    console.log(event);
  }

  cdkDropListExited(event: any) {
    console.log(event);
  }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Apply the CSS style specifically to the initial row in the table

Is there a way to target the first row of a table with a different tr class using CSS? <div id="right"> <table> <tbody> <tr class="head"> <td >Date</td><td>Info</td><td>More</td> </tr> ...

Display text with a hover effect

When I hover over an image, I want to display some text. I managed to make it work, but the text was expanding the size of the card. To solve this issue, I added a display none to the text class. I can't include all the code here, so here's a sn ...

Is there a way to make the table header stretch across the entire table when using display properties to simulate a <table>?

I made a switch from an old table to a new one constructed using Divs, and everything seems to be working fine except for one issue. I am trying to create a header that spans the entire width of the table without having multiple cells in the heading like i ...

Ways to invoke main.ts to communicate with an Angular component using Electron

I have a good understanding of how to communicate between an angular app and the electron main thread using IPC. However, in my current scenario, I have threads running in the electron main thread for video processing. After these threads complete their t ...

connecting a BehaviorSubject to the [disabled] property of a button

My component has a variable refreshButtonEnabled$ = new BehaviorSubject<boolean>(true); and also a button <button [disabled]="!refreshButtonEnabled$ | async">refresh</button> However, I encountered the following error message: ...

I am experiencing issues with the loading of CSS and JavaScript files in my recently created Laravel project

Recently, I received a Laravel project and successfully downloaded its configuration to get it up and running using php artisan serve. Upon attempting to access the project through localhost:8000, only the HTML content is displayed without any styling fro ...

Angular - Display shows previous and current data values

My Angular application has a variable called modelResponse that gets updated with new values and prints them. However, in the HTML, it also displays all of its old values along with the new ones. I used two-way data binding on modelResponse in the HTML [( ...

Is there a more efficient method for horizontally and vertically aligning in this particular scenario using HTML and CSS?

Embarking on my HTML/CSS journey, I am taking on the challenge of creating my very first website. Currently tackling the final CSS project for Codecademy. I've been tinkering with this task for what feels like an eternity and just can't seem to ...

Create a sleek and uniform design with Bootstrap by setting up three columns that maintain the same height

I am attempting to design a 3 column div that maintains equal height for all responsive rows, each containing an ICON and information. <div class="container"> <div class="row row-eq-height"> <div class="col c ...

Perfectly Aligning Image at the Center of the Screen

I'm having trouble centering a loading image on my screen. It seems to be centered closer to the bottom rather than in the middle. Any suggestions on how I can adjust it to be more centered vertically? Edit: I also want it to look good on mobile devi ...

I'm looking for a way to have an element shift in a particular direction only when two keys are pressed simultaneously

Having trouble moving a square diagonally when two keys are pressed simultaneously. Trying to create an if statement that detects both key presses at the same time and triggers the movement. However, all attempts have failed so far, leaving uncertainty abo ...

Tips for utilizing comment tags efficiently

I have encountered an issue with IE7 where my CSS is not functioning properly. In an attempt to target IE7 and lower versions specifically, I inserted IE comment tags into the HTML code. However, despite my efforts, it does not seem to be effective. Initia ...

What CSS style should be used to fill both the thumbs up and thumbs down icons of a glyphicon?

Using glyphicon icons instead of other icons (fa icons), I am able to change the color of the icon, but it does not completely fill the icon with color like Facebook's like button. <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1 ...

What is causing the body to be partially hidden on the right side of every mobile device screen?

I'm currently addressing the mobile optimization issues on a website that I've been developing for some time, and I've encountered my first obstacle. When viewing it on an iPad, the body of the site doesn't extend all the way to the rig ...

Switching to Angular's routing, prioritize removal of the previous component

I'm currently using [routerLink]="['my-route']" in my Angular project. However, I've encountered an issue with the routing system where it renders the new component first and then removes the old one from the DOM. This is caus ...

The <img> tag needs to dynamically adjust its size based on the width of its parent element, while ensuring it does not exceed its original dimensions

I spent hours working on my tribute page project on codepen and managed to pass 9 test cases. However, no matter what I try, I just can't seem to pass the last test case. My CSS code: #img-div { display: block; filter: grayscale(100%); width: 1 ...

Restrict the character count in the input field according to its width

Is there a way to restrict the number of characters in an input field based on its width? I have a dynamic input field with varying widths and I would like users to be able to type without their text extending outside of the input boundary. Using maxLeng ...

Utilizing Angular to call a function defined in Renderer2 and assign it to a

In my directive, I have configured a table value to be replaced by an anchor tag using the renderer.setProperty method. The anchor tag is enhanced with a "click" attribute that I am unsure how to interact with: either through accessing the function "onCli ...

Generating a PDF file from HTML div content using a button click

I am looking to export a specific div section as a PDF file. The div contains a mix of text, images, and charts. <div id="newdiv"> <img src="http://imgsv.imaging.nikon.com/lineup/lens/zoom/normalzoom/af-s_dx_18-140mmf_35-56g_ed_vr/img/sample/ ...