Angular:如何构建像 Outlook 一样的全屏日历
首先让我们来看看 Angular 组件
第二,让我们看看CalendarDay类是什么样子的
第三,让我们在日历中填写所需的日期
第四,让我们添加一些 HTML 和 CSS 来实际显示我们的日历
第五,现在是时候解释和展示块管道的代码了
不久前,在一个 Angular 项目中,我需要像 Outlook 那样显示全屏日历。作为一个懒惰的开发者,我开始在网上寻找可以实现这个功能的 NPM 包。
结果出乎意料的是,我没有找到任何可以 100% 满足我需求的包,所以我自己动手做了一个!
这是最终结果:
附言:请对我好一点,HTML 和 CSS 不是我的强项。
以下是我的编码过程:
首先让我们来看看 Angular 组件
这是我们的起点,一个 Angular 组件和一个数组,用于保存日历显示的日期
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
public calendar: CalendarDay[] = [];
}
第二,让我们看看CalendarDay类是什么样子的
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);
}
}
让我们稍微解释一下构造函数。
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);
我设置了属性isPastDate,以便我的日历知道如何显示或禁用过去的日期,并设置了 isToday属性,以便 UI 知道如何绘制今天的日期。
我使用.setHours(0,0,0,0)的原因是因为我想确保我比较的是一天的开始,并且小时并不重要。
第三,让我们在日历中填写所需的日期
我的代码中有注释来解释其逻辑。
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;
}
第四,让我们添加一些 HTML 和 CSS 来实际显示我们的日历
在 HTML 中,你会看到我正在使用一个名为chunk的管道,我将稍微解释一下它的用法和代码
<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);
}
第五,现在是时候解释和展示块管道的代码了
由于我们的日历数组有 42 个元素,但我们希望在每一行显示 7 个元素,因此块管道将创建一个数组,其中每周一个数组内有 6 个数组。
@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;
}
}
这篇文章充满爱意❤️
鏂囩珷鏉ユ簮锛�https://dev.to/rickystam/how-to-build-a-full-screen-calendar-like-outlook-in-angular-5dcg