Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular @Input value is undefined

Passing a value from parent to child. The value that is received in the child component is undefined.

Here is my app.component with a working example

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';

interface ItemsResponse {
   data: any[];
}
@Component({
   selector: 'my-app',
   templateUrl: './app.component.html',
   styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit  {
   constructor(private http: HttpClient) {}
   ngOnInit() {
      this.getPosts();
      console.log(this.name); // name is undefined
   }
   name;
   results:Array<any> = []; // code changed
   getPosts() {
      this.http.get<ItemsResponse>('https://reqres.in/api/users?page=3')
      .subscribe(res => this.name = res); // code changed
   }
}

Here is my hello.component with a working example, where the data is passed to the child component. As you can see the name that is passed from parent to child component through Angular's @Input decorator is undefined in the constructor.

import { Component, Input } from '@angular/core';

@Component({
   selector: 'hello',
   template: `<pre>{{name | json}}</pre>`,
   styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent  {
   @Input() name: string;
}

and in the hello.component

import { Component, Input } from '@angular/core';

@Component({
   selector: 'hello',
   template: `<h1>hi</h1><pre>{{name | json}}</pre>`,
   styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent  {
   ngOnInit() {
   console.log('name', this.name); // name is undefined
}
   @Input() name: string;
}
like image 298
Karty Avatar asked Nov 19 '17 09:11

Karty


1 Answers

First of all, your code is asynchronous, so your console.log needs to be inside the subscribe:

.subscribe(res => {
   this.name = res
   console.log(this.name);
})

Please check this for more info: How do I return the response from an Observable/http/async call in angular2?

Second of all, you want to pass the object to your child, so instead of

<hello name="{{ name }}"></hello>

you want to do:

<hello [name]="name"></hello>

DEMO

And since this is asynchronous, name will initially be undefined, as it takes some time for response to come. You can use OnChanges in child to track when the value arrives. OnChanges is fired whenever there is a change in a @Input value. So you can conditionally check if the value is there, and when it is, do whatever you need to do with it.

ngOnChanges() {
  if(this.name) {
    console.log(this.name)
  }
}

https://stackblitz.com/edit/angular-rpc1vy?file=app/hello.component.ts

like image 126
AT82 Avatar answered Oct 03 '22 08:10

AT82