@HostListner ו-@HostBinding

@HostListner

@HostListner decorator מקשיב לאירועים מה-DOM של האלמנט ומגיב לאירוע על ידי ביצוע של event handler.

בדוגמא נראה איך גורמים ל-div לשנות את המרווחים שלו עם טרנזקציה כשמבוצעת פעולת hover. הפונקציה נעבוד על האלמנט "המארח", כלומר זה שקרא ל-directive.

כשהאירוע mouseenter יקרה באלמנט המארח, הפונקציה onmouseover תתבצע.

בתוך אותו ה-directive אנחנו יכולים להאזין לאירועים נוספים, למשל לאירוע העזיבה של העכבר את האלמנט.

hover.directive.ts

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

@HostListener('mouseenter') 
onmouseover(){
    this.renderer.setStyle(this.element.nativeElement, 'margin', '30px');
    this.renderer.setStyle(this.element.nativeElement, 'padding', '10px');
    this.renderer.setStyle(this.element.nativeElement, 'transition', '0.5s');
}

@HostListener('mouseleave')
onmouseout(){
    this.renderer.setStyle(this.element.nativeElement, 'margin', '10px');
    this.renderer.setStyle(this.element.nativeElement, 'padding', '20px');
    this.renderer.setStyle(this.element.nativeElement, 'transition', '0.5s');
}

app.component.html

<div appHover>Some content</div>

@HostBinding

@HostBinding מחבר property של אלמנט מארח למשתנה ב-directive.

ניצור property ל-directive בשם background. ל-background נשתמש ב-decorator של @HostBinding. ל-@HostBinding ניתן html property. למשל את ה-property שהגדרנו ב-directive, את ה-background אנחנו רוצים להצמיד ל-property של html שהיא background.

כשאנחנו נקרא ל-directive של appBetterhighlight על אלמנט יש לו תכונה של backgoundColor. ואז אנחנו שמים את הערך transparent לתכונה הזאת.

betterhighlight.directive.ts

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

@HostBinding('style.backgoundColor') background: string = 'yellow';

app.component.html

<div appBetterhighlight>Some content</div>

נקח צעד קדימה ונגיד שאנחנו רוצים שבכל פעם שהגולש עובר מעל ל-div אנחנו רוצים לשנות את הצבע שלו.

betterhighlight.directive.ts

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

@HostBinding('style.backgoundColor') background: string = 'transarent';

@HostListener('mouseenter')
onmouseover(){
    this.background = 'pink';
}

@HostListener('mouseleave')
onmouseout(){
    this.background = 'transarent';
}

נוסיף עכשיו שינוי של גבול האלמנט.

betterhighlight.directive.ts

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

@HostBinding('style.backgoundColor') background: string = 'transarent';
@HostBinding('style.border') border: string = 'none';

@HostListener('mouseenter')
onmouseover(){
    this.background = 'pink';
    this.border = 'red 2px solid';
}

@HostListener('mouseleave')
onmouseout(){
    this.background = 'transarent';
    this.border = 'none';
}

Binding Directive Properties

בדוגמא למעלה השתמשנו בצבעים שכתובים במפורש ב-directive. מה אם אנחנו רוצים לקבל את הצבע מתוך האלמנט עצמו?

ניצור שני משתנים ב-directive שלנו. נחליף את המקומות ששמנו בהם צבעים בערכים של שני שמשתנים האלה.

betterhighlight.directive.ts

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

defaultColor: string = 'transparent';
highlightColor: string = 'pink';

@HostBinding('style.backgoundColor') background: string = this.defaultColor;
@HostBinding('style.border') border: string = 'none';

@HostListener('mouseenter')
onmouseover(){
    this.background = this.highlightColor;
    this.border = 'red 2px solid';
}

@HostListener('mouseleave')
onmouseout(){
    this.background = this.defaultColor;
    this.border = 'none';
}

השלב הבא הוא לקבל את הערכים של המשתנים האלה מתוך האלמנט שקורא ל-directive.

נגדיר את המשתנים כ-Input. עכשיו אנחנו יכולים לחבר את הערכים שלהם לקומפוננטה.

betterhighlight.directive.ts

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

@Input() defaultColor: string = 'transparent';
@Input() highlightColor: string = 'pink';

@HostBinding('style.backgoundColor') background: string = this.defaultColor;
@HostBinding('style.border') border: string = 'none';

@HostListener('mouseenter')
onmouseover(){
    this.background = this.highlightColor;
    this.border = 'red 2px solid';
}

@HostListener('mouseleave')
onmouseout(){
    this.background = this.defaultColor;
    this.border = 'none';
}

app.component.html

<div appBetterhighlight [defaultColor]="'yellow'" [highlightColor]="'red'">Some content</div>

הערך ההתחלתי שתקבל התכונה יהיה זה שמוגדר בערך ברירת המחדל ב-directive. כדי להתגבר על זה נגדיר את ngOnInit.

betterhighlight.directive.ts

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

@Input() defaultColor: string = 'transparent';
@Input() highlightColor: string = 'pink';

@HostBinding('style.backgoundColor') background: string = this.defaultColor;
@HostBinding('style.border') border: string = 'none';

ngOnInit(){
    this.background = this.defaultColor;
}

@HostListener('mouseenter')
onmouseover(){
    this.background = this.highlightColor;
    this.border = 'red 2px solid';
}

@HostListener('mouseleave')
onmouseout(){
    this.background = this.defaultColor;
    this.border = 'none';
}

Direct binding

בדוגמא למעלה אנחנו קוראים ל-directive בתוך אלמנט ה-html ואז שולחים לכל פרמטר את הערך שלו בנפרד.

אפשר לשלוח את הפרמטר ביחד עם השם של ה-directive וזה מתאים במיוחד אם יש לנו חיבור לתכונה אחת שאנחנו רוצים לשנות.

איך עושים את זה?

מקשרים את הפרמטר לשם של ה-directive דרך ה-input.

betterhighlight.directive.ts

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

@Input() defaultColor: string = 'transparent';
@Input('appBetterhighlight') highlightColor: string = 'pink';

@HostBinding('style.backgoundColor') background: string = this.defaultColor;
@HostBinding('style.border') border: string = 'none';

ngOnInit(){
    this.background = this.defaultColor;
}

עכשיו נשתמש ישירות ב-directive כדי לשנות את הערך של highlightColor.

app.component.html

<div [appBetterhighlight]="'red'" [defaultColor]="'yellow'">Some content</div>