Перейти к содержанию

Взаимодействие с пользователем, @HostListener и @HostBinding

Кроме простой установки значений атрибутивная директива может взаимодействовать с пользователем. Для этого применяется декоратор @HostListener.

Возьмем директиву BoldDirective и добавим в нее взаимодействие с пользователем:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import {
    Directive,
    ElementRef,
    Renderer2,
    HostListener,
} from '@angular/core';

@Directive({
    selector: '[bold]',
})
export class BoldDirective {
    constructor(
        private element: ElementRef,
        private renderer: Renderer2
    ) {
        this.renderer.setStyle(
            this.element.nativeElement,
            'cursor',
            'pointer'
        );
    }

    @HostListener('mouseenter') onMouseEnter() {
        this.setFontWeight('bold');
    }

    @HostListener('mouseleave') onMouseLeave() {
        this.setFontWeight('normal');
    }

    private setFontWeight(val: string) {
        this.renderer.setStyle(
            this.element.nativeElement,
            'font-weight',
            val
        );
    }
}

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

Кроме кода директивы менять больше ничего не надо, код компонента и модуля остаются теми же.

@HostBinding

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import {
    Directive,
    HostListener,
    HostBinding,
} from '@angular/core';

@Directive({
    selector: '[bold]',
})
export class BoldDirective {
    private fontWeight = 'normal';

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

    @HostBinding('style.cursor') get getCursor() {
        return 'pointer';
    }

    @HostListener('mouseenter') onMouseEnter() {
        this.fontWeight = 'bold';
    }

    @HostListener('mouseleave') onMouseLeave() {
        this.fontWeight = 'normal';
    }
}

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

Свойство host

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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
    ) {
        this.renderer.setStyle(
            this.element.nativeElement,
            'cursor',
            'pointer'
        );
    }

    onMouseEnter() {
        this.setFontWeight('bold');
    }
    onMouseLeave() {
        this.setFontWeight('normal');
    }
    private setFontWeight(val: string) {
        this.renderer.setStyle(
            this.element.nativeElement,
            'font-weight',
            val
        );
    }
}

Результат работы директивы в данном случае будет аналогичен, только теперь все события и связанные с ними обработчики определяются с помощью параметра host:

1
2
3
4
host: {
    '(mouseenter)': 'onMouseEnter()',
    '(mouseleave)': 'onMouseLeave()'
}

Комментарии