Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 bind input to function call

Is it acceptable to bind @Input() property of child component to a function call of parent component, for example:

<navigation 
        [hasNextCategory]="hasNextCategory()"
        [hasPreviousCategory]="hasPreviousCategory()"
        (nextClicked)="nextCategory()"
        (previousClicked)="previousCategory()"
        (submitClicked)="submit()"
</navigation>

This seems to work, but I wonder how. Are those inputs re-evaluated when event is fired from component, or what drives the input binding?

like image 219
Tuomas Toivonen Avatar asked Jun 01 '16 18:06

Tuomas Toivonen


1 Answers

Sure. The function is called every time change detection runs and assigns the result of the function call to the input property.

You get an exception in devMode when 2 successive calls return different values. like

hasNextValue() {
  return {};
}

Exception: Expression has changed ...

It is discouraged to bind to functions. Rather assign the result to a property and bind to this property. If you know what you are doing it's fine though.

update

so returning true / false according to some internal state is not allowed? Strange that my navigation still works

This is actually allowed. If your state changes because of some event (click, timeout, ...) then Angular change detection expect changes. If Angular change detection calls the method twice (as it does in devMode) without any event happening in between, then it doesn't expect changes and throws the exception mentioned above. What Angular doesn't like is when change detection itself causes changes.

Below example would also cause an exception because change detection itself would modify the components state (this.someState = !this.someState;) which is not allowed.

someState:boolean = false;
hasNextValue() {
  this.someState = !this.someState;
  return this.someState;
}

Two successive calls would return false and true even when no event happened in between.

This example would work fine though

someState:boolean = false;

@HostListener('click') {
  this.someState = !this.someState;
}

hasNextValue() {
  return this.someState;
}

because two successive calls (without any event in between) would return the same value.

like image 192
Günter Zöchbauer Avatar answered Oct 13 '22 02:10

Günter Zöchbauer