Unable to Cancel Card Movement in Kanban Component Using Asynchronous Validation

Hello Syncfusion team,

I am currently using the Kanban component in Angular and I’ve encountered a limitation when trying to prevent a card from being moved based on asynchronous conditions.

I would like to conditionally cancel a card movement based on a server-side validation (async HTTP call).
If the condition fails, I want the card to remain in its original column and not trigger the actionComplete or change visually.

- I tried using the (dragStop) event and setting args.cancel = true inside a subscription, but it doesn’t work because the Kanban component already completed the drag action.

Since the validation is asynchronous, this comes too late.

actionComplete is also not suitable, as it is fired after the card is already moved.

Code Example :

public onCardDragStop(args: DragEventArgs): void {
  const draggedCardId = args.data[0].id;


  this.kanbanService
    .checkConditionsVisibility(draggedCardId) // async call
    .pipe(
      catchError(() => of({ visibility: false }))
    )
    .subscribe((res) => {
      if (!res.visibility) {
        args.cancel = true; // Has no effect, too late
        this.snackbar.warn('You are not allowed to move this card.');
      }
    });
}


public dataSourceChanged(state: DataSourceChangedEventArgs): void {
  if (state.requestType === 'cardChanged' && state.changedRecords?.length) {
    const cardId = state.changedRecords[0].id;


    this.kanbanService.updateCard(state, this.kanban.content, this.kanban.id)
      .pipe(
        tap(response => this.processCardUpdates(response, state))
      )
      .subscribe();
  }
}

Thank you in advance for your help,

Best regards,

Romain DEVAUX


1 Reply

VJ Vinitha Jeyakumar Syncfusion Team July 9, 2025 09:56 AM UTC

Hi Romain DEVAUX,

Your requirement to prevent the dropping of a dragged card based on the asynchronous conditions in the dragStop event can be achieved by getting the dragged card's details from the dragStart event. 
The dragStop event is triggered when a card is dropped after being dragged. However, if this event is marked as async and awaits a response before completing execution, the drop action will still proceed, and the card will be placed in its new position. This happens because the dragStop event is a synchronous function, meaning that asynchronous operations (such as awaiting a backend response) cannot be handled directly within it.
 
To achieve your requirement, follow these steps:
  1. Use the dragStart event to store the initial column before the drag starts.
  2. In the dragStop event, perform an asynchronous request (e.g., backend validation using setTimeout for simulation).
  3. If the backend validation fails, update the card's status to its previous value and use the updateCard method to revert the card to its original column dynamically.

Code snippet:
 
 <ejs-kanban
      #kanbanObj
      cssClass="kanban-overview"
      keyField="Status"
      [dataSource]="kanbanData"
      [cardSettings]="cardSettings"
      enableTooltip="true"
      [swimlaneSettings]="swimlaneSettings"
      [dialogSettings]="dialogSettings"
      (cardRendered)="cardRendered($event)"
      (dragStop)="onDragStop($event)"
      (dragStart)="onDragStart($event)"
     
    >
onDragStart(args: any): void {
    const card = args.element;
    const parent = card.parentElement;
    this.dragIndex = Array.from(parent.children).indexOf(card);

    this.previousStatus = args.data[0].Status; // Store initial status
  }

  // Perform backend validation and undo if necessary
  onDragStop(args: any): void {
    const draggedCard = { ...args.data[0] }; // Clone dragged card data
    const newStatus = args.data[0].Status;

    // Simulate backend validation (replace with actual API call)
    setTimeout(() => {
      const backendValidationPassed = false; // Simulating failure response

      if (!backendValidationPassed) {
        // Restore the card to its previous status
        draggedCard.Status = this.previousStatus;
        this.kanbanObj.updateCard(draggedCard, this.dragIndex);
      }
    }, 10); // Simulated async delay
  }
}



https://ej2.syncfusion.com/angular/documentation/api/kanban#dragstop


Regards,
Vinitha
    

Loader.
Up arrow icon