Skip to content

Commit e2538a1

Browse files
committed
feat(week-view): allow events to be dragged outside of the view
BREAKING CHANGE: if you were extending the week view component then the internal API has changed slightly and you may need to adjust your app Closes #516
1 parent 2aaaeb8 commit e2538a1

File tree

6 files changed

+225
-72
lines changed

6 files changed

+225
-72
lines changed

demos/demo-modules/draggable-external-events/component.ts

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { colors } from '../demo-utils/colors';
1616
.drag-active {
1717
position: relative;
1818
z-index: 1;
19+
pointer-events: none;
1920
}
2021
.drag-over {
2122
background-color: #eee;

demos/demo-modules/draggable-external-events/template.html

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
[viewDate]="viewDate"
4646
[events]="events"
4747
[refresh]="refresh"
48+
[snapDraggedEvents]="false"
4849
(eventTimesChanged)="eventDropped($event)">
4950
</mwl-calendar-week-view>
5051
<mwl-calendar-day-view

src/modules/day/calendar-day-view.scss

+6-2
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,11 @@
9191
border: solid 1px;
9292
}
9393

94-
.cal-drag-active * {
95-
pointer-events: none;
94+
.cal-drag-active {
95+
z-index: 1;
96+
97+
& * {
98+
pointer-events: none;
99+
}
96100
}
97101
}

src/modules/week/calendar-week-view.component.ts

+83-63
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ import { CalendarDragHelper } from '../common/calendar-drag-helper.provider';
2424
import { CalendarResizeHelper } from '../common/calendar-resize-helper.provider';
2525
import { CalendarEventTimesChangedEvent } from '../common/calendar-event-times-changed-event.interface';
2626
import { CalendarUtils } from '../common/calendar-utils.provider';
27-
import { validateEvents, trackByIndex } from '../common/util';
27+
import { validateEvents, trackByIndex, roundToNearest } from '../common/util';
2828
import { DateAdapter } from '../../date-adapters/date-adapter';
29+
import { DragEnd } from 'angular-draggable-droppable/draggable.directive';
2930

3031
export interface WeekViewEventResize {
3132
originalOffset: number;
@@ -51,48 +52,54 @@ export interface CalendarWeekViewBeforeRenderEvent {
5152
@Component({
5253
selector: 'mwl-calendar-week-view',
5354
template: `
54-
<div class="cal-week-view" #weekViewContainer>
55+
<div class="cal-week-view">
5556
<mwl-calendar-week-view-header
5657
[days]="days"
5758
[locale]="locale"
5859
[customTemplate]="headerTemplate"
5960
(dayHeaderClicked)="dayHeaderClicked.emit($event)"
6061
(eventDropped)="eventTimesChanged.emit($event)">
6162
</mwl-calendar-week-view-header>
62-
<div *ngFor="let eventRow of view.eventRows; trackBy:trackByIndex" #eventRowContainer class="cal-events-row">
63-
<div
64-
*ngFor="let weekEvent of eventRow.row; trackBy:trackByEventId"
65-
#event
66-
class="cal-event-container"
67-
[class.cal-draggable]="weekEvent.event.draggable"
68-
[class.cal-starts-within-week]="!weekEvent.startsBeforeWeek"
69-
[class.cal-ends-within-week]="!weekEvent.endsAfterWeek"
70-
[ngClass]="weekEvent.event?.cssClass"
71-
[style.width]="((100 / days.length) * weekEvent.span) + '%'"
72-
[style.marginLeft]="((100 / days.length) * weekEvent.offset) + '%'"
73-
mwlResizable
74-
[resizeEdges]="{left: weekEvent.event?.resizable?.beforeStart, right: weekEvent.event?.resizable?.afterEnd}"
75-
[resizeSnapGrid]="{left: dayColumnWidth, right: dayColumnWidth}"
76-
[validateResize]="validateResize"
77-
(resizeStart)="resizeStarted(weekViewContainer, weekEvent, $event)"
78-
(resizing)="resizing(weekEvent, $event, dayColumnWidth)"
79-
(resizeEnd)="resizeEnded(weekEvent)"
80-
mwlDraggable
81-
dragActiveClass="cal-drag-active"
82-
[dragAxis]="{x: weekEvent.event.draggable && currentResizes.size === 0, y: false}"
83-
[dragSnapGrid]="{x: dayColumnWidth}"
84-
[validateDrag]="validateDrag"
85-
(dragPointerDown)="dragStart(weekViewContainer, event)"
86-
(dragEnd)="eventDragged(weekEvent, $event.x, dayColumnWidth)">
87-
<mwl-calendar-week-view-event
88-
[weekEvent]="weekEvent"
89-
[tooltipPlacement]="tooltipPlacement"
90-
[tooltipTemplate]="tooltipTemplate"
91-
[tooltipAppendToBody]="tooltipAppendToBody"
92-
[customTemplate]="eventTemplate"
93-
[eventTitleTemplate]="eventTitleTemplate"
94-
(eventClicked)="eventClicked.emit({event: weekEvent.event})">
95-
</mwl-calendar-week-view-event>
63+
<div
64+
#weekEventsContainer
65+
mwlDroppable
66+
(drop)="eventDroppedWithinContainer = true">
67+
<div *ngFor="let eventRow of view.eventRows; trackBy:trackByIndex" #eventRowContainer class="cal-events-row">
68+
<div
69+
*ngFor="let weekEvent of eventRow.row; trackBy:trackByEventId"
70+
#event
71+
class="cal-event-container"
72+
[class.cal-draggable]="weekEvent.event.draggable"
73+
[class.cal-starts-within-week]="!weekEvent.startsBeforeWeek"
74+
[class.cal-ends-within-week]="!weekEvent.endsAfterWeek"
75+
[ngClass]="weekEvent.event?.cssClass"
76+
[style.width]="((100 / days.length) * weekEvent.span) + '%'"
77+
[style.marginLeft]="((100 / days.length) * weekEvent.offset) + '%'"
78+
mwlResizable
79+
[resizeEdges]="{left: weekEvent.event?.resizable?.beforeStart, right: weekEvent.event?.resizable?.afterEnd}"
80+
[resizeSnapGrid]="{left: dayColumnWidth, right: dayColumnWidth}"
81+
[validateResize]="validateResize"
82+
(resizeStart)="resizeStarted(weekEventsContainer, weekEvent, $event)"
83+
(resizing)="resizing(weekEvent, $event, dayColumnWidth)"
84+
(resizeEnd)="resizeEnded(weekEvent)"
85+
mwlDraggable
86+
dragActiveClass="cal-drag-active"
87+
[dropData]="{event: weekEvent.event}"
88+
[dragAxis]="{x: weekEvent.event.draggable && currentResizes.size === 0, y: !snapDraggedEvents && weekEvent.event.draggable && currentResizes.size === 0}"
89+
[dragSnapGrid]="snapDraggedEvents ? {x: dayColumnWidth} : {}"
90+
[validateDrag]="snapDraggedEvents ? validateDrag : false"
91+
(dragPointerDown)="dragStarted(weekEventsContainer, event)"
92+
(dragEnd)="dragEnded(weekEvent, $event, dayColumnWidth)">
93+
<mwl-calendar-week-view-event
94+
[weekEvent]="weekEvent"
95+
[tooltipPlacement]="tooltipPlacement"
96+
[tooltipTemplate]="tooltipTemplate"
97+
[tooltipAppendToBody]="tooltipAppendToBody"
98+
[customTemplate]="eventTemplate"
99+
[eventTitleTemplate]="eventTitleTemplate"
100+
(eventClicked)="eventClicked.emit({event: weekEvent.event})">
101+
</mwl-calendar-week-view-event>
102+
</div>
96103
</div>
97104
</div>
98105
</div>
@@ -171,6 +178,11 @@ export class CalendarWeekViewComponent implements OnChanges, OnInit, OnDestroy {
171178
*/
172179
@Input() weekendDays: number[];
173180

181+
/**
182+
* Whether to snap events to a grid when dragging
183+
*/
184+
@Input() snapDraggedEvents: boolean = true;
185+
174186
/**
175187
* Called when a header week day is clicked. Adding a `cssClass` property on `$event.day` will add that class to the header element
176188
*/
@@ -222,6 +234,11 @@ export class CalendarWeekViewComponent implements OnChanges, OnInit, OnDestroy {
222234
*/
223235
currentResizes: Map<WeekViewEvent, WeekViewEventResize> = new Map();
224236

237+
/**
238+
* @hidden
239+
*/
240+
eventDroppedWithinContainer = false;
241+
225242
/**
226243
* @hidden
227244
*/
@@ -302,7 +319,7 @@ export class CalendarWeekViewComponent implements OnChanges, OnInit, OnDestroy {
302319
* @hidden
303320
*/
304321
resizeStarted(
305-
weekViewContainer: HTMLElement,
322+
weekEventsContainer: HTMLElement,
306323
weekEvent: WeekViewEvent,
307324
resizeEvent: ResizeEvent
308325
): void {
@@ -311,9 +328,9 @@ export class CalendarWeekViewComponent implements OnChanges, OnInit, OnDestroy {
311328
originalSpan: weekEvent.span,
312329
edge: typeof resizeEvent.edges.left !== 'undefined' ? 'left' : 'right'
313330
});
314-
this.dayColumnWidth = this.getDayColumnWidth(weekViewContainer);
331+
this.dayColumnWidth = this.getDayColumnWidth(weekEventsContainer);
315332
const resizeHelper: CalendarResizeHelper = new CalendarResizeHelper(
316-
weekViewContainer,
333+
weekEventsContainer,
317334
this.dayColumnWidth
318335
);
319336
this.validateResize = ({ rectangle }) =>
@@ -373,27 +390,6 @@ export class CalendarWeekViewComponent implements OnChanges, OnInit, OnDestroy {
373390
this.currentResizes.delete(weekEvent);
374391
}
375392

376-
/**
377-
* @hidden
378-
*/
379-
eventDragged(
380-
weekEvent: WeekViewEvent,
381-
draggedByPx: number,
382-
dayWidth: number
383-
): void {
384-
const daysDragged: number = draggedByPx / dayWidth;
385-
const newStart: Date = this.dateAdapter.addDays(
386-
weekEvent.event.start,
387-
daysDragged
388-
);
389-
let newEnd: Date;
390-
if (weekEvent.event.end) {
391-
newEnd = this.dateAdapter.addDays(weekEvent.event.end, daysDragged);
392-
}
393-
394-
this.eventTimesChanged.emit({ newStart, newEnd, event: weekEvent.event });
395-
}
396-
397393
/**
398394
* @hidden
399395
*/
@@ -404,17 +400,41 @@ export class CalendarWeekViewComponent implements OnChanges, OnInit, OnDestroy {
404400
/**
405401
* @hidden
406402
*/
407-
dragStart(weekViewContainer: HTMLElement, event: HTMLElement): void {
408-
this.dayColumnWidth = this.getDayColumnWidth(weekViewContainer);
403+
dragStarted(weekEventsContainer: HTMLElement, event: HTMLElement): void {
404+
this.dayColumnWidth = this.getDayColumnWidth(weekEventsContainer);
409405
const dragHelper: CalendarDragHelper = new CalendarDragHelper(
410-
weekViewContainer,
406+
weekEventsContainer,
411407
event
412408
);
413409
this.validateDrag = ({ x, y }) =>
414410
this.currentResizes.size === 0 && dragHelper.validateDrag({ x, y });
411+
this.eventDroppedWithinContainer = false;
415412
this.cdr.markForCheck();
416413
}
417414

415+
/**
416+
* @hidden
417+
*/
418+
dragEnded(
419+
weekEvent: WeekViewEvent,
420+
dragEndEvent: DragEnd,
421+
dayWidth: number
422+
): void {
423+
if (this.eventDroppedWithinContainer) {
424+
const daysDragged = roundToNearest(dragEndEvent.x, dayWidth) / dayWidth;
425+
const newStart = this.dateAdapter.addDays(
426+
weekEvent.event.start,
427+
daysDragged
428+
);
429+
let newEnd: Date;
430+
if (weekEvent.event.end) {
431+
newEnd = this.dateAdapter.addDays(weekEvent.event.end, daysDragged);
432+
}
433+
434+
this.eventTimesChanged.emit({ newStart, newEnd, event: weekEvent.event });
435+
}
436+
}
437+
418438
private refreshHeader(): void {
419439
this.days = this.utils.getWeekViewHeader({
420440
viewDate: this.viewDate,

src/modules/week/calendar-week-view.scss

+6-2
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,11 @@
8282
white-space: nowrap;
8383
}
8484

85-
.cal-drag-active * {
86-
pointer-events: none;
85+
.cal-drag-active {
86+
z-index: 1;
87+
88+
& * {
89+
pointer-events: none;
90+
}
8791
}
8892
}

0 commit comments

Comments
 (0)