Hans
Hans

Reputation: 318

Pass API returning array data from Parent component to Child Component in Angular

In here i am trying to pass this.bookingInfo = bookings.responseObj.txnValues; bookingInfo array values to my child component.This is my parent component.

 @Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent implements OnInit{
  lineChart = ['line_chart1', 'line_chart2', 'line_chart3', 'line_chart4', 'line_chart5'];
  value = ['33.5M', '67.9M', '90.9M', '09.9M'];
  names = ['cancellations', 'Bookings', 'Modifications', 'Revenue' ];
  bookingInfo = [];

  ngOnInit() {

     this.getBookingInfo();
    }

  getBookingInfo() {
          const params = [];
          params.push({code: 'dateType', name: 'BOOKING'});
          params.push({code: 'fromDate', name: '2019-01-01'});
          params.push({code: 'toDate', name: '2019-12-31'});

          this.ServiceHandler.getTxnInfo([], params).subscribe(
            bookings => {
              this.bookingInfo = bookings.responseObj.txnValues;
              console.log(this.bookingInfo);
          });
      }

}

This is my dashboard.component.html

<app-summary-chips [lineChart]="lineChart[0]" [value] = "value[0]" [name] = "names[0]" [data] = "bookingInfo"></app-summary-chips>

This my child component.

@Component({
  selector: 'app-summary-chips',
  templateUrl: './summary-chips.component.html',
  styleUrls: ['./summary-chips.component.scss']
})
export class SummaryChipsComponent implements OnInit {
  @Input('lineChart') lineChart: string;
  @Input('value') value: string;
  @Input('name') name: string;
  @Input() data: [];

  ngOnInit() {

   console.log('line chart: ', this.lineChart);
    console.log(this.data);
  }

}

This is my summary-chips.component.html

<div class="l-content-wrapper c-summary-chip oh" >
  <div class="c-summary-chip__value">{{value}}</div>
  <div class="c-summary-chip__txt">{{name}}</div>
  <!--<i class="a-naked-label a-naked-label&#45;&#45;danger-down fa c-summary-chip__naked-lable"><span class="a-naked-label__span">100.00%</span></i>-->

  <div id= "{{lineChart}}" class="c-summary-chip__graph ">
  </div>
</div>

But when i console.log(this.data); in child component it prints an empty array.

Upvotes: 0

Views: 50

Answers (3)

Mayank yaduvanshi
Mayank yaduvanshi

Reputation: 170

You are getting empty list in your child component because the list is updating inside a subscription, this approach is not triggered the angular child component to detect the property changes.

One very quick solution to your problem is that you can pass the observable itself to child component and in the child, you subscribe to the value changes.

in your dashboard component:

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent implements OnInit{
  lineChart = ['line_chart1', 'line_chart2', 'line_chart3', 'line_chart4', 'line_chart5'];
  value = ['33.5M', '67.9M', '90.9M', '09.9M'];
  names = ['cancellations', 'Bookings', 'Modifications', 'Revenue' ];
  bookingInfoObservalbe;

  ngOnInit() {

     this.getBookingInfo();
    }

  getBookingInfo() {
          const params = [];
          params.push({code: 'dateType', name: 'BOOKING'});
          params.push({code: 'fromDate', name: '2019-01-01'});
          params.push({code: 'toDate', name: '2019-12-31'});

          this.bookingInfoObservalbe = this.ServiceHandler.getTxnInfo([], params)
      }

}

in your dashboard template

<app-summary-chips [lineChart]="lineChart[0]" [value] = "value[0]" [name] = "names[0]" [data] = "bookingInfoObservalbe"></app-summary-chips>

in your child component

@Component({
  selector: 'app-summary-chips',
  templateUrl: './summary-chips.component.html',
  styleUrls: ['./summary-chips.component.scss']
})
export class SummaryChipsComponent implements OnInit {
  @Input('lineChart') lineChart: string;
  @Input('value') value: string;
  @Input('name') name: string;
  @Input() data: [];
  bookingInfo = [];

  ngOnInit() {

   console.log('line chart: ', this.lineChart);
   this.data.subscribe(
            bookings => {
              this.bookingInfo = bookings.responseObj.txnValues;
              console.log(this.bookingInfo);
          });
  }

}

you can find the working sample of this on Stackblitz, Hope this will be helpful.

Upvotes: 1

Sajeetharan
Sajeetharan

Reputation: 222672

You are not where setting the data or assigning the value to data. If you want to set data to the variable you need to initialize or set the data that is being passed from the parent component

EDIT

You are trying to pass asynchronous data to child component. You have different solutions to do that. For exemple, you can use ngOnChanges instead of ngOnInit:

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

Another solution is to use *ngIf, in order to delay the initialization of posts components:

<app-summary-chips *ngIf="bookingInfo" [lineChart]="lineChart[0]" [value] = "value[0]" [name] = "names[0]" [data] = "bookingInfo"></app-summary-chips>

Upvotes: 1

Shlok Nangia
Shlok Nangia

Reputation: 2377

as your service handler is taking time to fetch data, this.bookingInfo gets updated after some time so initially you wont get any value in child component.

To make it happen try to implement changeDetectionStrategy, please check the below links for better understanding

https://alligator.io/angular/change-detection-strategy/

https://angular.io/api/core/ChangeDetectionStrategy

after implementing this ,when this.bookingsInfo is updated thenngOnChanges() of child component will be called containing the previous and the current(new) value of this.bookingsInfo instead of onInit()

Upvotes: 1

Related Questions