Создание 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);
}
}