1

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

EMahan K
  • 417
  • 1
  • 19

4 Answers4

3

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

ayala
  • 331
  • 1
  • 9
  • 1
    Can you send me stackblitz? – EMahan K Jul 12 '22 at 19:31
  • 1
    The observable is not necessary and if it were, you would use the async pipe from the parent to the child and not in the child html. The child doesnt have to know where the data is coming from or if its async. – ukn Jul 12 '22 at 19:31
  • 2
    @ayala this is better! – ukn Jul 12 '22 at 19:37
  • 1
    The [stackblitz](https://stackblitz.com/edit/angular-ivy-f2vvmu?file=src%2Fapp%2Fapp.component.html,src%2Fapp%2Fdetails%2Fdetails.component.ts,src%2Fapp%2Fdetails%2Fdetails.component.html,src%2Fapp%2Fapp.component.ts) – ayala Jul 12 '22 at 19:38
1

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

1

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
  };
ukn
  • 1,723
  • 1
  • 14
  • 24
1

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