Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 expression parser and ng-init directive

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?

like image 471
Estus Flask Avatar asked Aug 29 '16 15:08

Estus Flask


People also ask

What is the use of ng-init directive?

The ng-init Directive is used to initialize AngularJS Application data. It defines the initial value for an AngularJS application and assigns values to the variables. The ng-init directive defines initial values and variables for an AngularJS application.

What is ngInit?

The ngInit directive allows you to evaluate an expression in the current scope. This directive can be abused to add unnecessary amounts of logic into your templates. There are only a few appropriate uses of ngInit : aliasing special properties of ngRepeat , as seen in the demo below.

Can we call function in ng-init?

Calling a function or initializing a single value on page load in AngularJS is quite easy. AngularJS provides us with a dedicated directive for this specific task. It's the ng-init directive. Example 1: In this example, we will call a function to initialize a variable on page load.

What is the naming convention of built in directives in angular 2?

Naming Convention: *[name of directive] — Upper camel case is used for the directive class, while lower camel case is used for the directive's name. What sets them apart from other directives in Angular 2: Reshape DOM structure by adding or removing existing DOM elements and do not have templates.


2 Answers

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!');
  }
}
like image 66
Ankit Singh Avatar answered Oct 08 '22 19:10

Ankit Singh


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 }}
like image 43
Estus Flask Avatar answered Oct 08 '22 19:10

Estus Flask