Angular. Изменение функциональности компонентов с помощью директив
На текущем проекте мы используем библиотеку компонентов от PrimeNG, и в ~20 местах повторяется следующий код для компонента календаря вида:
<p-calendar
formControlName="begin"
[minDate]="operationalPlanMinDate"
[maxDate]="operationalPlanMaxDate"
[showIcon]="true"
[showTime]="true"
[firstDayOfWeek]="1"
[readonlyInput]="true"
hourFormat="24"
dateFormat="dd.mm.yy"
></p-calendar>
В статье Use Angular directives to extend components that you don't own приводится лаконичное решение с использованием директивы для настройки сторонних компонентов:
import { Directive } from '@angular/core';
import { Calendar } from 'primeng/calendar';
@Directive({
selector: 'p-calendar[sopDatetimeCalendar]',
})
export class SopDatetimeCalendarDirective {
constructor(private calendar: Calendar) {
this.calendar.dateFormat = 'dd.mm.yy';
this.calendar.firstDayOfWeek = 1;
this.calendar.hourFormat = '24';
this.calendar.readonlyInput = true;
this.calendar.showIcon = false;
this.calendar.showTime = true;
}
}
В результате HTML шаблон упрощается:
<p-calendar
formControlName="begin"
[minDate]="operationalPlanMinDate"
[maxDate]="operationalPlanMaxDate"
sopDatetimeCalendar
[showIcon]="true" <!-- можно переопределять -->
></p-calendar>
Вариант приминения для расширения ngFor
trackByKey директива, чтобы каждый раз не создавать функцию trackBy
import { NgForOf } from '@angular/common';
import { Directive, Input } from '@angular/core';
@Directive({ selector: '[ngFor]' })
export class NgForTrackByKeyDirective<T = any> {
constructor(private ngForRef: NgForOf<T>) {}
@Input()
set ngForTrackByKey(key: keyof T) {
if (key) {
this.ngForRef.ngForTrackBy = (_index, item) => item[key];
}
}
}
Приминение
<div *ngFor="let item of list; trackByKey: 'id'">
{{ item.id }} - {{ item.value }}
</div>
Посмотреть на результат: