0
votes

I am trying to create the following component architecture. A parent component with a large template that is a placeholder for many children components. The parent component is responsable for getting data from the server. The parent module also has a service to serve data to children components. Actual data subscription is taking a place in the child component. Here is some relevant code: Generic child component:

import { Component, OnDestroy, OnInit, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
import { DataSvcService } from '../../dashboard/data-svc.service';

@Component({
 selector: 'app-generalstatistics',
 templateUrl: './generalstatistics.component.html',
 styleUrls: ['./generalstatistics.component.css']
})
export class GeneralstatisticsComponent implements OnInit, OnDestroy, AfterViewInit  {
@ViewChild('generalstatistics', {static: false}) span: ElementRef;
subscription;
generalStatistics = new Array({});

constructor(private dataSvc: DataSvcService) {}

ngOnInit() {
  this.subscription = this.dataSvc.generalstatistics.subscribe(data => {
  this.generalStatistics = data;
 });
}
ngAfterViewInit() {
  console.log(this.span);
}
ngOnDestroy() {
  this.subscription.unsubscribe();
}
}

Template: generalstatistics.component.html

<span #generalstatistics></span>

Parent component (implementation template):

<div class="card-body pb-0">
    <app-generalstatistics></app-generalstatistics>
</div>

Parent component service: '../../dashboard/data-svc.service'

import { BehaviorSubject, Subject, Observable } from 'rxjs';
import { Injectable } from '@angular/core';

@Injectable()
export class DataSvcService {

constructor() { }
  public generalstatistics = new BehaviorSubject<Array<object>>([{}]);

public get generalStatistics(): Observable<Array<object>> {
  return this.generalstatistics.asObservable();
}
}

Parent component data request:

this.http.get<any>(`${environment.apiUrl}/api/
 home/`)
.subscribe((data: any) => {
  this.dataSvcService.generalstatistics.next(data);
});

My idea is that I want to have generalstatistics as a generic component. Actual data binding should take place in the parent component. I am trying adding something like this in the implementation:

<app-generalstatistics **#someid**></app-generalstatistics>

So I could identify it in the generalstatistics component code and assign the data to the span element. But when I check for this.span.nativeElement I dont see anything coming from the actual implementation.

My question is how do I bind data to a child component in my solution? Shuold I change the whole architecture?

Thanks

2
Can I just confirm - you just want the data in generalStatistics of your parent, to actually be shown in your child component?cmprogram
Yes, that's correct.Mark
And based on your comments to another answer, you do not know statically how many child components you'll have, is this also correct? i.e. You may have one child component, if the data requires it, or you may have several.cmprogram
Well, I do know how many child components I am going to have. The reason I want to use one generic control is because they are all will be the same just showing different data.Mark

2 Answers

0
votes

Did you try this? In your parent component you can pass like this:

<app-generalstatistics [id]="someid" ></app-generalstatistics>

In your generalstatistics component.ts you can receive in this way:

@Input() id;
0
votes

Let's assume that your service is correctly returning your array of objects that you're looking for. All you need to do is then bind that data down to your child component.

So in your child component, it would simply have the following in the ts file.

@Input() data: any; // You can replace "any" with an interface of the expected object

Then in your parent html file, if you know the order in which the data is returned, you can bind the data statically, like so:

<app-generalstatistics
[data]="this.generalStatistics[0]"
>

<app-generalstatistics
[data]="this.generalStatistics[1]"
>

Or if you're unsure of how many objects will be in your array, you can simply specify:

<app-generalstatistics *ngFor="let gS of generalStatistics"
[data]="gS"
>

With any of the strategies above, you can remove your ViewChild(), elementRef, as you ultimately aren't using it again in your ts file.