Developing attribute directive
The basic
Feature - highlight an element with attribute directive
it('should highlight element', () => {
const fixture = createGenericTestComponent(`
<div myHighlight>Content</div>
`, TestComponent);
const elemnt = fixture.debugElement.query(By.css('div')).nativeElement;
expect(elemnt.style['background-color']).toBe('yellow');
});
Create directive with selector [myHighlight]
import { Directive, ElementRef } from '@angular/core';
@Directive({
selector: '[myHighlight]'
})
export class MyHighlightDirective {
constructor(private elementRef: ElementRef) {
elementRef.nativeElement.style['background-color'] = 'yellow';
}
}
- Use
@Directive
to define the class as a Directive. selector
defines aCSS selector
to identify the HTML element that is associated with the directive.elementRef
is an injected reference for accessing the element in our directive.- We change the
background-color
withnativeElement
property.
Why we use myHighlight
instead of highlight
?
- To ensure they don’t conflict with
standard HTML attribute
. - To reduce the risk of colliding with
third-party directives
. - Do not use
ng
prefix because it belongs to Angular
How to use our directive?
- First of all, we need to add
MyHighlightDirective
to the module’sdeclarations
. - And then, associate with an element like
<p myHighlight>Content</p>
. - Element
<p>
is thehost
of the directive.
Adding event listener to the host element associated with directive
Feature - when mouseenter, background-color will be green. when mouseleave, it recovers
it('should change the background-color when mouse enter', () => {
const fixture = createGenericTestComponent(`
<div myHighlight>Content</div>
`, TestComponent);
const elemnt: HTMLDivElement = fixture.debugElement.query(By.css('div')).nativeElement;
elemnt.dispatchEvent(new Event('mouseenter'));
expect(elemnt.style['background-color']).toBe('green');
elemnt.dispatchEvent(new Event('mouseleave'));
expect(elemnt.style['background-color']).toBe('yellow');
});
Listen to mouse event with @HostListener
decorator
@HostListener('mouseenter') onMouseEnter() {
this.changeBackgroundColor('green');
}
@HostListener('mouseleave') onMouseLeave() {
this.changeBackgroundColor('yellow');
}
private changeBackgroundColor(color: string) {
this.elementRef.nativeElement.style.backgroundColor = color;
}
@HostListener
listen to the event ofhost element
Bind a color with @Input()
Feature - define the highlight color with an element attribute
it('should define the highlight color by attribute', () => {
const fixture = createGenericTestComponent(`
<div myHighlight highlightColor="pink">Content</div>
`, TestComponent);
const elemnt = fixture.debugElement.query(By.css('div')).nativeElement;
expect(elemnt.style['background-color']).toBe('pink');
});
Get highlightColor with @Input() decorator
@Input() highlightColor = 'yellow';
constructor(private elementRef: ElementRef) {
}
ngOnInit(): void {
this.changeBackgroundColor(this.highlightColor);
}
- We can’t set highlight color with
constructor
any more, binding @Input valueruns after
constructor. - We move the code to
ngOnInit
method which runs after constructor and input binding
OnNgInit - Initialize the directive/component after Angular first displays the data-bound properties and sets the directive/component’s input properties.