How to create a directive which to color and display the input numeric value. The important part is the directive to detect changes and to react on the input value change.
Here is my example code:
//our root app component
import {Directive, Component, NgModule, Input, OnInit, OnDestroy, ElementRef} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<h2>Random number: <span my-value [value]="num"></span></h2>
</div>
`,
})
export class App implements OnInit, OnDestroy {
name: string;
num: number = 100;
private interval: any;
constructor() {
this.name = 'Angular2';
}
ngOnInit() {
this.interval = setInterval(() => {
this.num = this.getRandomInt(-100, 100);
}, 1000);
}
ngOnDestroy {
clearInterval(this.interval);
}
private getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
}
@Directive ({
selector: '[my-value]'
})
export class MyValueDirective {
@Input() value: number;
constructor(private el: ElementRef) {
}
ngOnInit(): void {
if (this.value < 0) {
this.el.nativeElement.style.color = 'red';
} else {
this.el.nativeElement.style.color = 'blue';
}
this.el.nativeElement.innerHTML = this.value;
}
}
@NgModule({
imports: [ BrowserModule ],
declarations: [ App, MyValueDirective ],
bootstrap: [ App ]
})
export class AppModule {}
Thank you!
Place the code updating the style inside the directive's ngOnChanges()
method instead of the ngOnInit()
method.
Angular calls the ngOnChanges()
method whenever it detects changes to input properties of the directive. See https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#onchanges
@Directive ({
selector: '[my-value]'
})
export class MyValueDirective {
@Input() value: number;
constructor(private el: ElementRef) {}
ngOnChanges(changes: SimpleChanges) {
const value = changes['value'];
if (value < 0) {
this.el.nativeElement.style.color = 'red';
} else {
this.el.nativeElement.style.color = 'blue';
}
this.el.nativeElement.innerHTML = value;
}
}
ADDITIONAL IMPROVEMENT: Why not use the same name for the selector
AND the @Input()
?
@Directive ({
selector: '[myValue]'
})
export class MyValueDirective {
@Input() myValue: number;
// ...
}
Now you can use your directive like this (more compact):
<span [myValue]="num"></span>