Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@Input() value is always undefined

I have created a user photo component which takes an @Input() value, this value is the userId. If the value is passed in then I retrieve information from Firebase linking to this userId, if it doesn't then I do something else.

My user-photo component

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

@Component({
    selector: 'user-photos',
    templateUrl: './user-photos.component.html',
    styleUrls: ['./user-photos.component.css']
})

export class UserPhotoComponent implements OnInit {

    @Input() userId: string;

    constructor() { 

        console.log('userId is:',this.userId);

    }


    ngOnInit() {


    }

    ngOnDestroy() {

    }
}

As you can see I have declared the userId as @Input(), now on my edit-profile component I have the following:

<user-photos [userId]="TestingInput"></user-photos>

Now the User Photo component gets rendered as I see the h1 tag appearing, however the userId is always undefined ?

No errors are appearing in the developer console, so I'm not entirely sure what I've done wrong.

like image 984
Code Ratchet Avatar asked Feb 08 '17 20:02

Code Ratchet


3 Answers

It will be initialized in ngOnInit, not the constructor. (Please also review the Angular Life Cycle Hooks documentation.)

ngOnInit() {
  console.log('userId is:',this.userId);
}

Also if you want to pass a literal like a string and use brackets [] you have to pass it as a string by enclosing the value with single ticks.

<user-photos [userId]="'TestingInput'"></user-photos>

The reason for that is the containing expression is evaluated in the context of the containing component so without it it will try to retrieve and pass a property/field named TestingInput which will be undefined (unless you also happen have a field by that name).

like image 74
Igor Avatar answered Nov 09 '22 11:11

Igor


In my case i had to use *ngIf = "isLoaded" on the parent's template first.

On Parent Component

    <div *ngIf = "isLoaded">
       <app-child-component [dataToChild]="dataFromParent"> </app-child-component>
    </div>

On Child Component

      @Input() dataToChild: any;
        constructor() { }
        ngOnInit(): void {
             console.log(this.dataToChild);
         }
like image 30
David Njuguna Avatar answered Nov 09 '22 10:11

David Njuguna


If your input comes delayed (e.g. a slow webservice), the value will at first be undefined until the response arrives from the webservice.

In order to debug this, you could use ngOnChanges() hook, which will fire every time, an input value changes:

ngOnChanges() {
  console.log('data', this.data);
}

which will output something like:

data undefined <- OnInit, value did not arrive yet

data here it is! <- value arrives delayed

like image 15
Johannes Hinkov Avatar answered Nov 09 '22 11:11

Johannes Hinkov