1

When I try to pass ASYNC data from parent to child component, I'm getting undefined message.

Because of ASYNC data, I suppose data coming from parent is not yet bound at OnInit.

In parent.component.html :

<my-child [childdata]="parentdata"></my-child>

In parent.component.ts :

interface SpotBB {
    id: number;
    name: string;
}
...
export class ParentComponent implements OnInit {
  parentdata: Observable<SpotBB[]>;
  ...
  ngOnInit() {
    this.parentdata = this.spotsservice.getSpots();
    // Call a service - Data stored in Firestore
  }

In child.component.html :

<button (click)="mycheck()">TEST</button>
<div *ngFor="let spot of childdata | async" >    
    {{ spot.id }} --- {{ spot.name }}     <!-- Works fine -->
</div>

In child.component.ts :

interface SpotBB {
    id: number;
    name: string;
}
...
export class ChildComponent implements OnInit {
  @Input() childdata: Observable<SpotBB[]>;
  copydata: Observable<SpotBB[]>;
  ...
  mycheck() {
    alert(JSON.stringify(this.copydata));   // --> !!! undefined !!!
  }
  ngOnInit() {
    this.copydata = this.childdata;  // COPY DATA NOT WORKING
  }
4
  • have you tried by console in the child component's ngOnInit like this console.log(this.childdate) Commented May 12, 2018 at 9:37
  • First of all, Observable do not fetch data if you don't subscribe it. log the this.childdata on OnInit. Let me know it is undefined or not. Commented May 12, 2018 at 9:37
  • console.log(this.childdate) (in OnInit) is undefined. Commented May 12, 2018 at 11:24
  • add *ngIf condition. <my-child *ngIf=" parentdata" [childdata]="parentdata"></my-child>. It will load child component after getting value from parent component. Commented Feb 6, 2019 at 12:11

2 Answers 2

4

You can implement several options to get it wokring:

1. Listen for changing @Input in your child component using ngOnChanges:

// child component
export class ChildComponent implements OnInit {
  @Input() childdata;
  ngOnChanges(changes: SimpleChanges) {
    // on loading you can access childdata
    console.log(changes.childdata.currentValue);
  }

2. Using set in child component for childdata:

// child component
export class ChildComponent implements OnInit {
  private _childdata;
  @Input() set childdata(value) {
    this._childdata = value;
  }


  // get method for childdata (for *nfFor in template)
  get childdata() {
    return this._childdata;
  }

3. Make child component available (if it is acceptable) only after parentdata will be available:

parent component html:

<my-child *ngIf="parentDataLoaded" [childdata]="parentdata"></my-child>

In parent.component.ts :

interface SpotBB {
  id: number;
  name: string;
}
...
export class ParentComponent implements OnInit {
  parentdata: Observable<SpotBB[]>;
  parentDataLoaded: false;
  ...
  ngOnInit() {
    this.spotsservice.getSpots()
      .subscribe(res => {
         // here is your successful results
         this.parentdata = res;
         this.parentDataLoaded = true;
      });
  }

For all options, I'm guessing to subscribe to getSpots, receive parentdata in your parent component and assign to this.parentdata:

// parent component
ngOnInit() {
  this.spotsservice.getSpots()
    .subscribe(res => {
      // here is your successful results
      this.parentdata = res;
    });
 }

 // child component html
 // *ngIf needs only if listening for changing
 // of childdata in child component
 <div *ngIf="childdata">
   <div *ngFor="let spot of childdata" >    
    {{ spot.id }} --- {{ spot.name }}     <!-- Works fine -->
   </div>
 </div>
Sign up to request clarification or add additional context in comments.

Comments

0

Instead of @Input() childData to @Input() set childData will work. This will get the childData to be refreshed on change.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.