0
votes

I have a child component inheriting from parent component.

Parent component is doing an api request and passing data to child component.

Parent component:

export class ChartComponent implements OnInit {

    @Input()
    protected exercisesData: any[];
    @Input()
    protected weightData: any[];

    /**
     *
     */
    constructor(public dataService: DataService) {
    }

    ngOnInit(): void {
        this.dataService.setEndpoint('/api/dashboard/get');
        this.get();
    }

    private get() {
        this.dataService
            .Get()
            .subscribe(data => {
                this.exercisesData = Object.assign({}, data);
                this.weightData = Object.assign({}, data);

                console.log(this.exercisesData);
                console.log(this.weightData);
            }, (error) => {
                console.log(error);
            });
    }
}

Child component:

export class ExercisesProgressChartComponent extends ChartComponent{

     private filterableData: any[];
     private dropDownSelectedValue: string;

    ngOnInit(): void {
        this.dropDownSelectedValue = "0";
        this.filterableData = Object.assign({}, this.exercisesData);
    }

    private onDropDownChange(dropDownSelectedValue) {

        if(dropDownSelectedValue == "0"){
            this.filterableData = Object.assign({}, this.exercisesData);
        }
        else{
        this.filterableData = Object.assign({}, this.exercisesData);
        this.filterableData["exercisesProgress"] = this.filterableData["exercisesProgress"].filter(x=>x.id == dropDownSelectedValue);
        }
    }

}

Template of child component:

<div *ngIf="exercisesData" class="dashboard">
   <div class="form-group">
          <select class="form-control" [(ngModel)]="dropDownSelectedValue" (ngModelChange)="onDropDownChange($event)" sele>
                      <option [value]="0">All Exercises</option>
                <option *ngFor="let x of exercisesData.exercisesProgress" [value]="x.id">{{x.name}}</option>
          </select>
          <small id="exerciseNameHelp" class="form-text text-muted">Please select exercise for filtering</small>
    </div>

    {{exercisesData.exercisesProgress | json}}
    {{filterableData.exercisesProgress | json}}

 <ngx-charts-line-chart
    [scheme]="{domain: ['#5AA454', '#A10A28', '#C7B42C', '#AAAAAA']}"
    [results]="filterableData.exercisesProgress"
    [gradient]="false"
    [xAxis]="true"
    [yAxis]="true"
    [legend]="true"
    [showXAxisLabel]="true"
    [showYAxisLabel]="true"
    [xAxisLabel]="Date"
    [yAxisLabel]="Weight"
    [autoScale]="true"
    (select)="onSelect($event)">
</ngx-charts-line-chart>
</div>

How can I make sure I can assign to this.filterableData when value is not undefined in Component itself? In template I can use *ngIf, but how can I do it in component level? Also dropDownSelectedValue is not assigned obviously because of *ngIf check in template.

2

2 Answers

1
votes

When the subscribe() returns the data, you have the opportunity to do something there. I see two options:

  • Keep in the ChartComponent only the get() as Observable and subscribe to it in the ChildComponent. So in that subscribe() you can reassign the result to the filterableData.
  • Keep the get() how it is and call a method in the Component which does the transformation, but in the Component it is empty, and you override it in the ChildComponent to do what you want there
0
votes

I resolved it without inheritance, since with inheritance it was still doing two requests.

I declared variable in parent component:

dashboardData: any[];

Then in template of parent component I passed dashboardData(it is array, but testProgress and testSecondProgress are nested arrays, and I passed each to corresponding child component):

<div *ngIf="dashboardData">
      <test-progress-chart [data]="dashboardData.testProgress"></test-progress-chart>
      <test-second-progress-chart [data]="dashboardData.testsecondProgress"></test-second-progress-chart>
</div>

Then in the child component where i want to pass data to I have declared a variable:

@Input()
data: any[];

For new comers, you can see linking behaviour:

dashboardData->[data]-> @Input data:any[]

Also important thing, to be able to have variable data filled in child component don't forget to wait for it before you render with *ngIf in parent template:

<div *ngIf="dashboardData">

since api requests are async and if you don't wait, it will try to render template before data is back, which throws an error data is undefined.