Home > Net >  How to pass data from parent component to child component angular 14
How to pass data from parent component to child component angular 14

Time:07-15

Trying to pass the array value from the parent component to the child component using httpclient get method. So, I have used an input decorator. But, In my code, I am not able to pass the array value. Because the child component is loaded before the parent component. That's why i am not able to pass the data inside the get method. How to resolve this issue?

app.component.ts:

    public allData = []; 
    constructor(private httpClient: HttpClient) {} 
    ngOnInit(): void {
    this.httpClient.get<string[]>('assets/data.json').subscribe((data) => {
      this.allData = data;
      console.log('GetData');
      console.log(data);
    });
    }

auto.component.ts:

  @Input() data: Array<string> = [];
  public rateData:any;
  
  constructor() {
   
  }

  ngOnInit(): void { 
    console.log("thisdata");
    console.log(this.data)
    this.rateData =this.data;
  }

Demo: https://stackblitz.com/edit/angular-ivy-1jw62m?file=src/app/auto/auto.component.ts

CodePudding user response:

The problem is that the ngOnInit lifecycle-hook runs at a specific point in time, after the constructor. Your GET-request is async and resolves at some unknown time, probably way after your child component is created. Thus, way past you child's ngOnInit has run. Thus, ngOnInit really has nothing to work with.

You have two options of fixing this: By using the ngOnChanges hook (a bit complex, not recommended), or by using a setter for the input, which will run whenever the input value changes. The latter I would recommend.

I have forked your project to demonstrate: https://stackblitz.com/edit/angular-ivy-va1se8?file=src/app/auto/auto.component.ts,src/app/auto/auto.component.html,src/app/app.component.ts

CodePudding user response:

You need to implement OnChanges interface and add ngOnChanges class method and manually update your field. OnInit recieves null and it does not get called later.

Docs: https://angular.io/api/core/OnChanges

app.component.ts

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
  name = 'Angular '   VERSION.major;

  public readonly allData$: Observable<string[]>; 

  constructor(private httpClient: HttpClient) {
    this.allData$ = this.httpClient.get<string[]>('assets/data.json');
  }

  ngOnInit(): void {}
}

app.component.html

<hello name="{{ name }}"></hello>
<p>Start editing to see some magic happen :)</p>

<app-auto [data]="allData$ | async"></app-auto>

auto.component.ts

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

@Component({
  selector: 'app-auto',
  templateUrl: './auto.component.html',
  styleUrls: ['./auto.component.css']
})
export class AutoComponent implements OnChanges {

  @Input() data: Array<string> = [];
  public rateData: string[] = [];
  
  constructor() {
  }
  
  ngOnChanges(changes: SimpleChanges) {
    this.rateData = changes.data.currentValue;
  }
}

auto.component.html

{{ rateData | json }}

CodePudding user response:

The problem is that the call is asynchronous so you have to use tools like ngOnChange hook for get the input change

https://www.stackchief.com/blog/ngOnChanges Example | Angular

CodePudding user response:

Yes you can add an onChanges to your child component and track the changes but if its just a matter of reacting to one single property change you can convert your @Input to setter/getter also e.g.

  private _data: string[];
  @Input() set data(val: string[]) {
    this._data = val;
    this.rateData = val;
  }
  get data(): string[] {
    return this._data;
  }

Updated: https://stackblitz.com/edit/angular-ivy-jfgmrs?file=src/app/app.component.html,src/app/app.component.ts,src/app/auto/auto.component.html,src/app/auto/auto.component.ts

However i would suggest that you change your parent component's change detection to OnPush and manually trigger change detection also. In Auto change detection, angualr is running cd unncessarily and you can trigger it only when you receive the data.

  • Related