Basically I'm looking for a way to implement a counterpart to Angular 1.x ngInit
directive.
I'm aware of ngOnInit
hook and the fact that it is the recommended place for initialization code. I consider ngInit
directive a quick, declarative way to prototype or fix a component that shouldn't be generally used in well-written production code (although a developer has the right to choose what's best for him/her).
Doing something like that in init
dummy directive
<p [init]="foo = 1; bar()"><p>
evaluates the expression more than one time and causes
Template parse errors:
Parser Error: Bindings cannot contain assignments
error.
In Angular 1.x it could be done just with
$parse($attrs.init)($scope)
How can Angular 2 parser be used and possibly extended to evaluate foo = 1; bar()
template expression on component initialization?
Just a Workaround ( Plunker Demo ), see estus's answer for a solution
init
Directive:
@Directive({
selector: '[init]',
inputs: ['init']
})
export class InitDir {
init;
ngOnChanges() { // `ngOnInit` if you want it to run just once
if(this.init){
let iife = function(str){ return eval(str); }.call(this.init[0], this.init[1]);
}
}
}
Usage:
@Component({
selector: 'my-app',
template: `
<div>
<h2 [init]="[this, 'this.name = 1; this.bar();']">Hello {{name}}</h2>
</div>
`,
})
export class App {
constructor() {
this.name = 'Angular2 (Release Candidate!)'
}
bar() {
alert('Yo Bar!');
}
}
This can be achieved with a directive:
@Directive({ selector: '[initialize]' })
class InitializeDirective {
@Output() initialize = new BehaviorSubject();
}
The expected use is:
<div (initialize)="initViaMethodCall(); foo = 'init via assignment'"></div>
<ng-template (initialize)="bar = 'init with no extra markup'"></template>
{{ foo }}
{{ bar }}