Создание aтрибутивных директив

Директива является простым классом с необходимой нам логикой. К этому классу необходимо дописать декоратор @Directive с определенными параметрами.

Давайте попробуем создать директиву которая будет делать текст жирным.

Создадим фаил bold.directive.ts со след. содержимым:

import { Directive, ElementRef, Renderer2, HostListener } from '@angular/core';

@Directive({
    selector: '[bold]'
})
export class BoldDirective {

    constructor(){
        console.log('BoldDirective');
    }

}

Мы создали класс BoldDirective c декоратором @Directive. В декораторе указали selector: '[bold]'. Это необходимо для вызова нашей директивы (ее название, аналогичное "ngClass").

Подключил директивы в наш модуль:

@NgModule({
  bootstrap: [ AppComponent ],
  declarations: [
    ...
    BoldDirective
  ],
  ....
})

И повесим наше директивы bold на html элемент:

<p bold>Some text</p>

После этого легко заметить что текст не изменился, но в консоли мы видим сообщение BoldDirective, которое написано в конструкторе. Из этого следует что директивы работает.

Сделаем так, чтоб текст становился жирным. Для этого модернизируем конструктор директивы:

  constructor(private element: ElementRef) {
    this.element.nativeElement.style = 'font-weight: bold';
  }

Мы подключили сервис ElementRef из @angular/core. ElementRef позволяет получит DOM элемент на котором висит наша директива.this.element.nativeElement- является DOM элементом. Мы можем работать с ним всеми возможными методами vanilla js. Но это не всегда удобно, мы же привыкли работать с DOM элементами через jQuery.

А ангуляре это возможно, но необходимо подключить jQuery. Так же есть другой способ, использовать сервис Renderer.

Давайте еще раз модернизируем наш конструктор:

  constructor(private element: ElementRef, private renderer: Renderer2) {
    this.renderer.setStyle(this.element.nativeElement, "font-weight", "bold");
  }

Мы использовали метод setStyle для установки нужного нам стиля.

Очень часто приходиться слушать различные события: скролл евент, ресайз страницы и тд. Для этого в ангуляре есть декоратор @HostListener.

Усовершенствуем нашу директивы и сделаем так, чтоб они наведении курсора на текст он становился жирным.

import { Directive, ElementRef, Renderer2, HostListener } from '@angular/core';

@Directive({
  selector: '[bold]'
})
export class BoldDirective{

  constructor(private element: ElementRef, private renderer: Renderer2) {
  }

  @HostListener("mouseenter") 
  public onMouseEnter() {
    this._setFontWeight("bold");
  }

  @HostListener("mouseleave") 
  public onMouseLeave() {
    this._setFontWeight("normal");
  }

  private _setFontWeight(val) {
    this.renderer.setStyle(this.element.nativeElement, "font-weight", val);
  }
}

Мы добавил метод onMouseEnter() и onMouseLeave() с декоратором @HostListener. Декоратор @HostListener позволяет связать события DOM и методы директивы. В частности, в декоратор передается название события, по которому будет вызываться метод. В данном случае мы привязываем события mouseenter (наведения указателя мыши на элемент) и mouseleave (уведение указателя мыши с элемента) к методу_setFontWeight(), который устанавливает стилевое свойство font-weight у элемента. Если мы наводим на элемент, то устанавливается выделение жирным. При отводе мыши выделение сбрасывается.

@HostBinding

Еще один декоратор - @HostBinding позволяет связать обычное свойство класса со свойством элемента, к которому применяется директива. Например, изменим код директивы следующим образом:

import { Directive, HostListener, HostBinding } from '@angular/core';

@Directive({
  selector: '[bold]'
})
export class BoldDirective{

  private _fontWeight = "normal";
  constructor(){}

  @HostBinding("style.fontWeight") get getFontWeight(){
    return this._fontWeight;
  }

  @HostListener("mouseenter") public onMouseEnter() {
    this._fontWeight ="bold";
  }

  @HostListener("mouseleave") public onMouseLeave() {
    this._fontWeight = "normal";
  }
}

Инструкция @HostBinding("style.fontWeight") get getFontWeight() связывает со свойством "style.fontWeight" значение, которое возвращается этим геттером getFontWeight. А он возвращает значение свойства fontWeight, которое также меняется при наведении указателя мыши.

Свойство host

Вместо применения декораторов @HostListener и @HostBinding для реагирования директивы на действия пользователя мы можем определить обработчики событий в декораторе @Directive с помощью его свойства host. Так, перепишем директиву следующим образом:

import { Directive, ElementRef, Renderer2 } from '@angular/core';

@Directive({
    selector: '[bold]',
    host: {
        '(mouseenter)': 'onMouseEnter()',
        '(mouseleave)': 'onMouseLeave()'
    }
})
export class BoldDirective{

    constructor(private element: ElementRef, private renderer: Renderer2) {
    }

    public onMouseEnter() {
        this._setFontWeight("bold");
    }
    public onMouseLeave() {
        this._setFontWeight("normal");
    }
    private _setFontWeight(val) {
        this.renderer.setStyle(this.element.nativeElement, "font-weight", val);
    }
}

results matching ""

    No results matching ""