Angular: Как создать полноэкранный календарь, такой как в Outlook

Angular: Как создать полноэкранный календарь, такой как в Outlook

От автора: некоторое время назад в проекте Angular мне нужно было отобразить полноэкранный календарь, такой как в outlook. Поэтому, как обычный ленивый разработчик, я начал искать в Интернете пакет NPM, который мог бы сделать эту работу.

К моему удивлению, я не нашел ничего, что могло бы покрыть мои потребности на 100%, поэтому я построил свой собственный календарь! Это конечный результат:

PS: Пожалуйста, будьте снисходительны ко мне, HTML и CSS не являются моей сильной стороной.

Вот история того, как я это сделал.

1-й давайте создадим компонент Angular

Это наша отправная точка, компонент Angular и массив, который будет содержать дни, для которых будет отображаться календарь.

JavaScript

123456789@Component({  selector: ‘my-app’,  templateUrl: ‘./app.component.html’,  styleUrls: [ ‘./app.component.css’ ]})export class AppComponent implements OnInit {  public calendar: CalendarDay[] = [];  }

2-й давайте посмотрим, как выглядит класс CalendarDay

JavaScript

12345678910111213export 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);  } }

Позвольте немного объяснить конструктор.

JavaScript

READ
Полноэкранное меню на CSS с эффектом анимации
12this.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, чтобы пользовательский интерфейс знал, как выводить сегодняшнюю дату.

Причина, по которой я использую .setHours (0,0,0,0), заключается в том, что я хочу быть уверен, что сравниваю начало дня, а часы не имеют значения.

3-й давайте заполним календарь необходимыми днями

У меня есть комментарии в коде, которые объясняют логику.

JavaScript

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647ngOnInit(): void {    // здесь мы инициализируем календарь    this.generateCalendarDays();  }   private generateCalendarDays(): void {    // мы сбрасываем календарь каждый раз    this.calendar = [];     // мы устанавливаем дату    let day: Date = new Date();     // здесь мы находим первый день, с которого начинается календарь    // это должен быть последний понедельник предыдущего месяца    let startingDateOfCalendar = this.getStartDateForCalendar(day);     // dateToAdd – это  an промежуточная переменная, которая увеличивается на 1     // в следующем цикле for    let dateToAdd = startingDateOfCalendar;     // ok, так как мы имеем начальную дату, когда получаем следующие 41 день    // нам нужно добавить в календарь массив    // 41 значит, что нужно отображать 6 недель, и математика говорит, что    // 6 недель * 7 дней = 42[HTML]    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){    // для дня, который мы выбрали, давайте получим последний день предыдущего месяца    let lastDayOfPreviousMonth = new Date(selectedDate.setDate(0));     // начинаем с установки для календаря начальной даты, совпадающей с последним днем предыдущего месяца    let startingDateOfCalendar: Date = lastDayOfPreviousMonth;     // но так как мы фактически хотим найти последний понедельник предыдущего месяца    // мы идем назад, пока не найдем последний понедельник предыдущего месяца    if (startingDateOfCalendar.getDay() != 1) {      do {        startingDateOfCalendar = new Date(startingDateOfCalendar.setDate(startingDateOfCalendar.getDate() – 1));      } while (startingDateOfCalendar.getDay() != 1);    }     return startingDateOfCalendar;  }
READ
Гнев интернет-сообщества вынудил Google изменить дизайн десктопной выдачи

В-четвертых, давайте добавим немного HTML и CSS, чтобы фактически отобразить календарь

В HTML вы увидите, что я использую пайп с именем chunk. Я немного объясню его использование и код.

1234567891011121314151617181920<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>

CSS

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849.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);}
READ
Google Chrome научился предупреждать пользователя о краже логина и пароля

5-й сейчас пришло время объяснить и показать код для пайпа chunk

Поскольку массив календаря содержит 42 элемента, но мы хотим показать 7 элементов в каждой строке, пайп chunk будет создавать массив из 6 массивов внутри для каждой недели.

JavaScript

123456789101112131415161718192021@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);        // здесь нам нужно использовать ++ перед переменной, иначе индекс увеличится        // после сравнения, а нам нужно, чтобы это происходило ДО        if (++index % chunkSize  === 0) {          calendarDays.push(weekDays);          weekDays = [];        }    });    return calendarDays;  }}

Этот пост был написан с любовью.

Автор: Ricky Stam

Редакция: Команда webformyself.

Источник

Оценить статью
Блог о самом интересном.
Добавить комментарий