Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2: Do something with @Input inside Component

Tags:

angular

How can I do something with the @Input value inside the component??

For example:

<log-user [user]="user"></log-user>

Let's assume that user is an object. Now, I know how I can pass this user data inside te log-user template, but how can I do something with this user inside its component??

LogUserComponent:

@Component({
  selector: 'log-user',
  template: `

    This works: {{user}}

  `
})

export class LogUserComponent {

  @Input() user:any;

  constructor() {
    // this get's logged as undefined??
    console.log(this.user);
  }
}

Any help would be great!! Thanks in advance!

like image 917
Aico Klein Ovink Avatar asked Jan 02 '16 16:01

Aico Klein Ovink


3 Answers

On construction time the @Input value is not yet set. How could Angular2 set the @Input value before the component was actually constructed?

You have to wait for the component to be initialized; meaning all @Input values have been set. You can do so by implementing the OnInit interface.

So to fix your example:

<log-user [user]="user"></log-user>

(Note: user must be a defined object, otherwise in this example undefined would still be logged. You can add *ngIf="user" to the log-user html tag to ensure the tag does not get rendered before user actually exists.)

Do:

import {Component, Input, OnInit} from 'angular2/core';

@Component({
  selector: 'log-user',
  template: `This works: {{user}}`
})
export class LogUserComponent implements OnInit {

  @Input() user:any;

  ngOnInit() {
    // this now gets logged as 'user'
    console.log(this.user);
  }
}

You can also just create the ngOnInit method on your component without implementing the interface, but by importing the OnInit interface you are ensured by the Typescript compiler not make a typo mistake.

The Angular docs about OnInit states:

Implement this interface to execute custom initialization logic after your directive's data-bound properties have been initialized.

ngOnInit is called right after the directive's data-bound properties have been checked for the first time, and before any of its children have been checked. It is invoked only once when the directive is instantiated.

like image 180
Lodewijk Bogaards Avatar answered Nov 16 '22 02:11

Lodewijk Bogaards


After some more research, I found this post "@Input property is undefined in angular 2's onInit".

So the answer is actually quite easy. Because in this example the user is an object coming from an API call, it is undefined at initialization of the component (hope I'm saying this the right way).. Using *ngIf fixes this:

<log-user *ngIf="user" [user]="user"></log-user>

like image 31
Aico Klein Ovink Avatar answered Nov 16 '22 03:11

Aico Klein Ovink


Since our Angular components are ES6 classes with a @Component() decorator we’re able to leverage TS accessors to intercept the injected value as follows:

The main difference is that instead of decorating the property we decorate the setter.

More details http://www.typescriptlang.org/docs/handbook/classes.html

<log-user [user]="user"></log-user>

Inside Component.ts

export class LogUserComponent {
  private _user:any;

  get user() {
    return this._user;
  }
  @Input() 
  set user( user:any) {
    // to catch undefined user 
    if(!user) return;
    this._user = user;
    // modify the user here example below
    // this._user = 'X' + user;
  }

  constructor() {

  }
}
like image 27
Faiz Mohamed Haneef Avatar answered Nov 16 '22 02:11

Faiz Mohamed Haneef