How to pass response updated data from parent to child component in angular 14

Viewed 140

Trying to pass the response data from parent to child component. I have used input decorator. But, it is not working. Previous values are only shown. So, How we can show the updated array response data. If anyone knows please help to find the solution.

app.component.ts:

  public allData = ['Van1', 'Hills2', 'Root3'];
  constructor(private dataService: DataService) {}

  ngOnInit(): void {
      this.dataService.getData().subscribe((data) => {
      this.allData = data;
      console.log(this.allData); // It is data.json data
  });
  }

Demo : https://stackblitz.com/edit/angular-ivy-67cnnt?file=src%2Fapp%2Fapp.component.ts

4 Answers

change the parent property to observable and use async pipe.
You can read more about asyncPipe and subscribe in observables here

like so:

data service code:

export class DataService {
  constructor(private http: HttpClient) {}

  getData(): Observable<string[]> {
    return this.http.get<string[]>('./assets/data.json');
  }
}

parent html code:

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

<details [data]="allData | async"></details>

parent ts code:

export class AppComponent implements OnInit {
  name = 'Angular ' + VERSION.major;

  public allData: Observable<string[]>;
  constructor(private dataService: DataService) {}

  ngOnInit(): void {
    this.allData = this.dataService.getData();
  }
}

child html code:

<ul>
  <li *ngFor="let detail of data">{{ detail }}</li>
</ul>

child ts code:

export class DetailsComponent implements OnInit {
 @Input() data: string[];
 constructor() {}

  ngOnInit() {
  }
}

It worked for me in stackblitz.
The result is:

enter image description here

If you want to pass data betweeen components , you should use to @Input @Output decorators. those decorators must be in the child component.

The problem is onInit is ran once and before data updates. Whats happenning is:

  1. parent oninit triggers the data fetch
  2. child is created, onInit(where you were assigning the data) runs but data is empty
  3. data comes back in the parent then passed to the child
  4. Missing part: assign the data after the update

What you need is a setter to your input like that: Stackblitz

detail component:

  _data: any = [];
  @Input() set data(array: any) {
    this._data = array;
    this.allInfo = array;
  };

  get data(): any {
    return this._data
  };

You are passing an observable to details.component, which then you are trying to assign and print in the template:

ngOnInit() {
  this.allInfo = this.data;
}

However, this.data is an observable, so you cannot assign it that way to display using curly brackets ({{}}). You need to subscribe (Also the async pipe has been suggested in other comments).

ngOnInit(){
  this.data.subscribe((x) => {
    this.allInfo = x;
  });
}

I've checked your stackblitz and this works (The information gets printed).

enter image description here

An explanation of what an observable is and how to use it can be found in the official angular documentation:

https://angular.io/guide/observables

Long story short, to view the values of an observable you subscribe to it and check the value in the payload.

Example in stackBlitz: https://stackblitz.com/edit/angular-ivy-mametc?file=src/app/details/details.component.ts

Related