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>

Посмотреть на результат:

Похожие записи

@Attribute() декоратор

Аналогично @Input() позволяет получить значение атрибута с хоста компонента/директивы, но не отслеживает дальнейшее изменение атрибута.

14 сентября 2019 г. в Angular

Angular. Когда не надо отписываться в RxJS?

В async pipe за вас отпишется Angular. Во всех остальных случаях лучше отписываться самостоятельно. Допускается не отписываться в потоках, где будет гарантировано вызван complete.

Angular. Manually retry http request

На память. Некоторое время назад я решил достаточно необычную задачу, но в последствии на backend`е переделали логику и код был удалён из проекта.