An Interest In:
Web News this Week
- April 1, 2024
- March 31, 2024
- March 30, 2024
- March 29, 2024
- March 28, 2024
- March 27, 2024
- March 26, 2024
Angular: How to build a full screen calendar like Outlook
In an Angular project a while back I needed to display a full screen calendar like the one in outlook. So as a good lazy developer I start looking on the web for a nmp package that could do the job.
To my surprise I didn't find anything that could cover my needs 100% so I went on and built one!
This is the end result:
P.S.: Please be kind with me, HTML and CSS are not my strong part.
Here is the coding story of how I did:
1st let's have our Angular component
This is our starting point an Angular component and an Array that will hold the days that our calendar will display
@Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: [ './app.component.css' ]})export class AppComponent implements OnInit { public calendar: CalendarDay[] = []; }
2nd let's see how the CalendarDay class looks like
export class CalendarDay { public date: Date; public title: string; public isPastDate: boolean; public isToday: boolean; constructor(d: Date) { this.date = d; this.isPastDate = d.setHours(0, 0, 0, 0) < new Date().setHours(0, 0, 0, 0); this.isToday = d.setHours(0, 0, 0, 0) == new Date().setHours(0, 0, 0, 0); }}
Let explain the constructor a little bit.
this.isPastDate = d.setHours(0, 0, 0, 0) < new Date().setHours(0, 0, 0, 0); this.isToday = d.setHours(0, 0, 0, 0) == new Date().setHours(0, 0, 0, 0);
I set property isPastDate so my calendar knows how to display or disable past dates and isToday property so UI knows how to draw the today's date.
The reason I use .setHours(0,0,0,0) is cause I want to be sure I'm comparing the beginning of the day and hours don't matter.
3rd let's populate our calendar with the needed days
I have comments in my code that explain the logic.
ngOnInit(): void { // here we initialize the calendar this.generateCalendarDays(); } private generateCalendarDays(): void { // we reset our calendar every time this.calendar = []; // we set the date let day: Date = new Date(); // here we find the first day that our calendar will start from // it would be the last Monday of the previous month let startingDateOfCalendar = this.getStartDateForCalendar(day); // dateToAdd is an intermediate variable that will get increased // in the following for loop let dateToAdd = startingDateOfCalendar; // ok since we have our starting date then we get the next 41 days // that we need to add in our calendar array // 41 cause our calendar will show 6 weeks and MATH say that // 6 weeks * 7 days = 42!! for (var i = 0; i < 42; i++) { this.calendar.push(new CalendarDay(new Date(dateToAdd))); dateToAdd = new Date(dateToAdd.setDate(dateToAdd.getDate() + 1)); } } private getStartDateForCalendar(selectedDate: Date){ // for the day we selected let's get the previous month last day let lastDayOfPreviousMonth = new Date(selectedDate.setDate(0)); // start by setting the starting date of the calendar same as the last day of previous month let startingDateOfCalendar: Date = lastDayOfPreviousMonth; // but since we actually want to find the last Monday of previous month // we will start going back in days intil we encounter our last Monday of previous month if (startingDateOfCalendar.getDay() != 1) { do { startingDateOfCalendar = new Date(startingDateOfCalendar.setDate(startingDateOfCalendar.getDate() - 1)); } while (startingDateOfCalendar.getDay() != 1); } return startingDateOfCalendar; }
4th let's add some HTML and CSS to actually start displaying our calendar
In the HTML you will see that I'm using a pipe named chunk I'll explain the use of it and the code in a bit
<table class='calendar-table' *ngIf="calendar"> <thead> <tr> <th>Monday</th> <th>Tuesday</th> <th>Wednesday</th> <th>Thursday</th> <th>Friday</th> <th>Saturday</th> <th>Sunday</th> </tr> </thead> <tbody> <tr *ngFor="let row of calendar | chunk: 7; let i = index"> <td class="calendar-day" [ngClass]="{'past-date': c.isPastDate, 'today': c.isToday}" *ngFor="let c of row; let j = index"> <div class="calendar-day-header" [ngClass]="{'blue-date': c.isToday}"><strong>{{c.date.getDate()}}</strong> <strong *ngIf="c.isToday || (i==0 && j==0) || (c.date.getDate() == 1)"> {{monthNames[c.date.getMonth()]}}</strong></div> </td> </tr> </tbody></table>
.calendar-table { border-collapse: collapse; width: 100%; max-width: 100%; margin-bottom: 1rem; border: 1px solid #dee2e6; background-color: #fff;}.calendar-table thead th { vertical-align: bottom; border-bottom: 2px solid #dee2e6; width: 14.2%;}.calendar-table td, .calendar-table th { border: 1px solid #dee2e6;}.calendar-table td, .calendar-table th { padding: .75rem; vertical-align: top; border-top: 1px solid #dee2e6;}.calendar-day { height: 12vh; max-height: 12vh; cursor: pointer;}.calendar-items-wrapper { margin-left: -10px; margin-right: -10px; overflow-y: auto; max-height: calc(100% - 20px);}.calendar-day.past-date { background-color: rgb(248, 248, 248);}.calendar-day:hover { background-color: rgb(248, 248, 248);}.blue-date { color: rgb(16, 110, 190);}
5th now it's time to explain and show the code for the chunk pipe
Since our calendar array has 42 elements but we want to show 7 elements in each row the chunk pipe will create an array with 6 arrays inside one array for each week.
@Pipe({ name: 'chunk'})export class ChunkPipe implements PipeTransform { transform(calendarDaysArray: any, chunkSize: number): any { let calendarDays = []; let weekDays = []; calendarDaysArray.map((day,index) => { weekDays.push(day); // here we need to use ++ in front of the variable else index increase //will happen after the evaluation but we need it to happen BEFORE if (++index % chunkSize === 0) { calendarDays.push(weekDays); weekDays = []; } }); return calendarDays; }}
This post was written with love
Original Link: https://dev.to/rickystam/how-to-build-a-full-screen-calendar-like-outlook-in-angular-5dcg
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To