I'm trying to create a calendar in Angular for a personal project. I have a table with a div for each day of the month and inside this div I have my appointments. What I want to do is be able to drag and drop my appointment from a day to another, I try with the angular cdk drag & drop but can't have something working.
Here is a cell of my table:
<div #dayCell class="day-cell" cdkDropList (cdkDropListDropped)="drop($event)">
<div>{{day.getDate()}}</div>
<div class="schedule-wrapper full-width">
<div cdkDrag *ngFor="let schedule of schedules" class="schedule" [style.width.px]="getScheduleWidth(schedule)">
<div class="schedule-details">
<div class="schedule-text">{{schedule.title}}</div>
</div>
</div>
</div>
</div>
in the drop function I add a console log of the day used in the cell, when I drag my appointment from a day to another the day logged is always the day before dragging.
Why ?
And anyone know how I can pass my appointment from a cell to another ?
EDIT: I'm trying to use the answer below but have some issues:
I have added the cdkDropListGroup
attribute to the tbody of my table (which show all the days)
And here is one cell of the table:
<div #dayCell class="day-cell" cdkDropList [cdkDropListData]="schedulesOfDay.schedulesWrapper" (cdkDropListDropped)="drop($event)">
<div>{{day.getDate()}}</div>
<div class="schedule-wrapper full-width">
<ng-container *ngFor="let scheduleWrapper of schedulesOfDay.schedulesWrapper">
<ng-container *ngIf="scheduleWrapper.isShowed">
<div >
<div class="schedule" cdkDrag
[style.width.px]="getScheduleWidth(scheduleWrapper)"
[style.height.px]="20"
[style.top.px]="getScheduleHeightOffset(scheduleWrapper)"
[style.background]="scheduleWrapper.schedule.background">
>
<div class="schedule-details">
<div class="schedule-text">{{getScheduleTitle(scheduleWrapper)}}</div>
</div>
</div>
</div>
</ng-container>
</ng-container>
</div>
</div>
I have the cdkDropList on the entire cell, and a cdkDrag for each of my schedules.
The problem is when I drag from a cell to another in the drop function the previousContainer
and container
are the same, so nothing is moved. (And I also print in console the day of the cell where the element is dropped and it always show the day where the schedule was before dragging).
I think the problem is the following:
When I move an element I need to change the date of this element (because I make a new render of my elements just after). But I can't get the specific moved element from the container, I can just have all the elements
One possible way to create multiple drag and drop zones is to use cdkDropListGroup
attribute on the parent element.
<div class="container" cdkDropListGroup>
<app-calendar *ngFor="let date of dates" [date]="date"></app-calendar>
</div>
Once you have this setup. Your app-calendar
component can have the following markup:
<div class="tasks" cdkDropList [cdkDropListData]="dayObj.schedules"
(cdkDropListDropped)="drop($event)">
<div *ngFor="let schedule of dayObj.schedules" cdkDrag>
{{ schedule.title }}
</div>
</div>
And then handling the drop:
drop(event: CdkDragDrop<any>) {
if (event.previousContainer === event.container) {
moveItemInArray(
event.container.data,
event.previousIndex,
event.currentIndex
);
} else {
transferArrayItem(
event.previousContainer.data,
event.container.data,
event.previousIndex,
event.currentIndex
);
}
}
These two methods moveItemInArray
and transferArrayItem
are from here:
import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
Working stackblitz.