Top


With 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.

calendar

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