Calendar
Official link Preview linkWith a busy schedule, users might need something to keep track of the upcoming events. A calendar app has been provided, where users can enter the upcoming events and a tag will be added in the calendar. Now you don't have to worry whether you will remember the next scheduled meeting.
Installation
ng add angular-calendar
calendar.component.html
<div class="card calender-basic">
<div class="card-body">
<div class="grid grid-cols-12 card-gap md:gap-4">
<div class="col-span-4 md:col-span-12 text-start md:text-center">
<div class="btn-group">
<div class="btn btn-outline-primary rounded-s-lg rounded-none" mwlCalendarPreviousView [view]="view" [(viewDate)]="viewDate"
(viewDateChange)="closeOpenMonthViewDay()">
Previous
</div>
<div class="btn btn-outline-primary rounded-none border-l-0 border-r-0" mwlCalendarToday [(viewDate)]="viewDate">
Today
</div>
<div class="btn btn-outline-primary rounded-e-lg rounded-none" mwlCalendarNextView [view]="view" [(viewDate)]="viewDate"
(viewDateChange)="closeOpenMonthViewDay()">
Next
</div>
</div>
</div>
<div class="col-span-4 md:col-span-12 text-center">
<h3>{{ viewDate | calendarDate:(view + 'ViewTitle'):'en' }}</h3>
</div>
<div class="col-span-4 md:col-span-12 text-end md:text-center">
<div class="btn-group">
<div class="btn btn-outline-primary rounded-s-lg rounded-none" (click)="setView(CalendarView.Month)"
[class.active]="view === CalendarView.Month">
Month
</div>
<div class="btn btn-outline-primary rounded-none border-l-0 border-r-0" (click)="setView(CalendarView.Week)"
[class.active]="view === CalendarView.Week">
Week
</div>
<div class="btn btn-outline-primary rounded-e-lg rounded-none" (click)="setView(CalendarView.Day)"
[class.active]="view === CalendarView.Day">
Day
</div>
</div>
</div>
</div>
<br />
<div>
@switch(view){
@case(CalendarView.Month){
<mwl-calendar-month-view [viewDate]="viewDate" [events]="events" [refresh]="refresh"
[activeDayIsOpen]="activeDayIsOpen" (dayClicked)="dayClicked($event.day)"
(eventClicked)="handleEvent('Clicked', $event.event)" (eventTimesChanged)="eventTimesChanged($event)">
</mwl-calendar-month-view>
}
@case(CalendarView.Week){
<mwl-calendar-week-view [viewDate]="viewDate" [events]="events" [refresh]="refresh"
(eventClicked)="handleEvent('Clicked', $event.event)" (eventTimesChanged)="eventTimesChanged($event)">
</mwl-calendar-week-view>
}
@case(CalendarView.Day) {
<mwl-calendar-day-view [viewDate]="viewDate" [events]="events" [refresh]="refresh"
(eventClicked)="handleEvent('Clicked', $event.event)" (eventTimesChanged)="eventTimesChanged($event)">
</mwl-calendar-day-view>
}
}
</div>
<br/><br/><br/>
<h3 class="mb-sm-3 mb-4">
Edit events
<button class="btn btn-primary float-end text-white" (click)="addEvent()">
Add new
</button>
<div class="clearfix"></div>
</h3>
<div class="table-responsive custom-scrollbar overflow-x-auto">
<table class="table table-bordered">
<thead>
<tr>
<th>Title</th>
<th>Primary color</th>
<th>Secondary + text color</th>
<th>Starts at</th>
<th>Ends at</th>
<th>Remove</th>
</tr>
</thead>
<tbody>
@for(event of events; track event){
<tr>
<td>
<input type="text" class="form-control" [(ngModel)]="event.title" (keyup)="refresh.next()" />
</td>
<td>
@if(event.color){
<input type="color" [(ngModel)]="event.color.primary" (change)="refresh.next()" />
}
</td>
<td>
@if(event.color){
<input type="color" [(ngModel)]="event.color.secondary" (change)="refresh.next()" />
}
@if(event.color){
<input type="color" [ngModel]="event.color.secondaryText ?? '#404040'"
(ngModelChange)="event.color.secondaryText = $event" (change)="refresh.next()" />
}
</td>
<td>
<input class="form-control" type="text" mwlFlatpickr [(ngModel)]="event.start"
(ngModelChange)="refresh.next()" dateFormat="Y-m-dTH:i" altFormat="F j, Y H:i" placeholder="Not set" />
</td>
<td>
<input class="form-control" type="text" mwlFlatpickr [(ngModel)]="event.end"
(ngModelChange)="refresh.next()" dateFormat="Y-m-dTH:i" altFormat="F j, Y H:i" placeholder="Not set" />
</td>
<td>
<button class="btn btn-danger text-white" (click)="deleteEvent(event)">
Delete
</button>
</td>
</tr>
}
</tbody>
</table>
</div>
@if(modalOpen){
<div class="modal fade show">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content create-event" (clickOutside)="modalClose()">
<div class="modal-header">
<h5 class="mb-0">Event action occurred</h5>
<button type="button" class="close btn-close" (click)="modalClose()"></button>
</div>
<div class="modal-body">
<div>
Action:
<pre>{{ modalDetails.action }}</pre>
</div>
<div>
Event:
<pre>{{ modalDetails.event | json }}</pre>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" (click)="modalClose()">
OK
</button>
</div>
</div>
</div>
</div>
}
</div>
</div>
calendar.component.ts
import { CommonModule } from '@angular/common';
import { Component, ViewEncapsulation } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { CalendarEvent, CalendarEventAction, CalendarEventTimesChangedEvent, CalendarModule, CalendarView } from 'angular-calendar';
import { addDays, addHours, endOfDay, endOfMonth, isSameDay, isSameMonth, startOfDay, subDays } from 'date-fns';
import { Subject } from 'rxjs';
import { OutsideDirective } from '../../shared/directives/outside.directive';
@Component({
selector: 'app-calendar',
imports: [CalendarModule, CommonModule, FormsModule,OutsideDirective],
encapsulation: ViewEncapsulation.None,
templateUrl: './calendar.component.html',
styleUrl: './calendar.component.scss'
})
export class CalendarComponent {
public view: CalendarView = CalendarView.Month;
public CalendarView = CalendarView;
public viewDate: Date = new Date();
public refresh = new Subject();
public activeDayIsOpen: boolean = true;
public color: string;
public modalDetails!: {
action: string;
event: CalendarEvent;
};
public colors = {
red: {
primary: '#7366FF',
secondary: '#e8e5ff',
},
blue: {
primary: '#838383',
secondary: '#f2f2f2',
},
yellow: {
primary: '#ffb829',
secondary: '#fff7e5',
},
};
public actions: CalendarEventAction[] = [
{
label: '',
a11yLabel: 'Edit',
onClick: ({ event }: { event: CalendarEvent }): void => {
this.handleEvent('Edited', event);
},
},
{
label: '',
a11yLabel: 'Delete',
onClick: ({ event }: { event: CalendarEvent }): void => {
this.events = this.events.filter((iEvent) => iEvent !== event);
this.handleEvent('Deleted', event);
},
},
];
public events: CalendarEvent[] = [
{
start: subDays(startOfDay(new Date()), 1),
end: addDays(new Date(), 1),
title: 'A 3 day event',
color: {primary: '#7366FF',
secondary: '#838383'},
actions: this.actions,
allDay: true,
resizable: {
beforeStart: true,
afterEnd: true,
},
draggable: true,
},
{
start: startOfDay(new Date()),
title: 'An event with no end date',
color: { ...this.colors['yellow'] },
actions: this.actions,
},
{
start: subDays(endOfMonth(new Date()), 3),
end: addDays(endOfMonth(new Date()), 3),
title: 'A long event that spans 2 months',
color: { ...this.colors['blue'] },
allDay: true,
},
{
start: addHours(startOfDay(new Date()), 2),
end: addHours(new Date(), 2),
title: 'A draggable and resizable event',
color: { ...this.colors['yellow'] },
actions: this.actions,
resizable: {
beforeStart: true,
afterEnd: true,
},
draggable: true,
},
];
public modalOpen: boolean = false;
dayClicked({ date, events }: { date: Date; events: CalendarEvent[] }): void {
if (isSameMonth(date, this.viewDate)) {
if (
(isSameDay(this.viewDate, date) && this.activeDayIsOpen === true) ||
events.length === 0
) {
this.activeDayIsOpen = false;
} else {
this.activeDayIsOpen = true;
}
this.viewDate = date;
}
}
eventTimesChanged({
event,
newStart,
newEnd,
}: CalendarEventTimesChangedEvent): void {
this.events = this.events.map((iEvent) => {
if (iEvent === event) {
return {
...event,
start: newStart,
end: newEnd,
};
}
return iEvent;
});
this.handleEvent('Dropped or resized', event);
}
handleEvent(action: string, event: CalendarEvent): void {
this.modalDetails = { event, action };
this.modalOpen = true
}
modalClose(){
this.modalOpen = false
}
addEvent(): void {
this.events = [
...this.events,
{
title: 'New event',
start: startOfDay(new Date()),
end: endOfDay(new Date()),
color: this.colors['red'],
draggable: true,
resizable: {
beforeStart: true,
afterEnd: true,
},
},
];
}
deleteEvent(eventToDelete: CalendarEvent) {
this.events = this.events.filter((event) => event !== eventToDelete);
}
setView(view: CalendarView) {
this.view = view;
}
closeOpenMonthViewDay() {
this.activeDayIsOpen = false;
}
}
Uninstalling Package
npm uninstall angular-calendar