Aico Klein Ovink
Aico Klein Ovink

Reputation: 1647

Angular 2: Do something with @Input inside Component

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!

Upvotes: 10

Views: 7971

Answers (3)

Faiz Mohamed Haneef
Faiz Mohamed Haneef

Reputation: 3596

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() {

  }
}

Upvotes: 2

Lodewijk Bogaards
Lodewijk Bogaards

Reputation: 19987

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.

Upvotes: 17

Aico Klein Ovink
Aico Klein Ovink

Reputation: 1647

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>

Upvotes: 7

Related Questions