简体   繁体   中英

Pass data from parent component to child component using input, how to implement?

There is a parent component with all the logic of the chart, you need to transfer data to the child component using @Input (), that is, so that I can display the chart in any of the components using @Input.

The parent component is logs.component and the child component is echarts.component. It is necessary to pass the data to LoadEcharts(), it contains all the logic of the Chart, that is, that I could call it on any html component

logs.components.ts

export class LogsComponent implements OnInit {
  sideNavStatus: boolean = false;
  subscription!: Subscription;
  logs!: Logs[];


  constructor(private dataService: DataService) {
  }

  columnDefs = [
    { headerName: 'Username', field: 'username', flex: 1},
    { headerName: 'Event', field: 'event', flex: 1 },
    { headerName: 'Date', field: 'date', flex: 1 }
  ];

  ngOnInit() {
    this.LoadLogs();
    this.LoadEcharts();
  }

  LoadLogs(): void {
    this.dataService.getLogs().subscribe(logs => this.logs = logs);
  }

  LoadEcharts(): void {
    const chartDom: HTMLElement = document.getElementById('main') as HTMLElement;
    const myChart = echarts.init(chartDom);

    this.subscription = this.dataService.getLogs().subscribe(data => {
      myChart.setOption(this.initBasicEchart(data))
    })
  }

  private initBasicEchart(data: Logs[]) {

    const result: any = {};

    data.forEach(el => {
      const date = el.date.toString().substring(0, 10);
      if (!result[el.event]) {
        result[el.event] = {};
        if (!result[el.event][date]) {
          result[el.event][date] = 1;
        }
      } else {
        if (!result[el.event][date]) {
          result[el.event][date] = 1;
        } else {
          result[el.event][date] += 1;
        }
      }
    });

    const login = {
      x: Object.keys(result.Login),
      y: Object.values(result.Login)};

    const reg = {
      c: Object.keys(result.Registration),
      z: Object.values(result.Registration)};

    return {
      title: {
        text: 'Graphic login and registration.'
      },
      tooltip: {},
      xAxis: {
        type: 'category',
        data: (reg.c, login.x)
      },
      yAxis: {
      },
      series: [
        {
          name: 'Login',
          type: 'bar',
          data: login.y,
        },
        {
          name: 'Registration',
          type: 'bar',
          data: reg.z,
        }
      ]
    };
  }
}

logs.component.html

<div class="container-fluid g-0">
    <app-header (sideNavToggled)="sideNavStatus = $event;"></app-header>

    <main>
        <app-sidebar [sideNavStatus]="sideNavStatus"
                     [ngClass]="{'app-side-nav-open': sideNavStatus}"></app-sidebar>

        <div class="display-area p-3" [ngClass]="{'display-area-shrink': sideNavStatus}">
            <p class="fs-1 fw-bold fst-italic text-center">Login and registration statistics.
            </p>

            <app-aggreed
                    *ngIf="logs"
                    [logs]="logs"
                    [columnDefs]="columnDefs"
            ></app-aggreed>

        </div>
    </main>
</div>

<app-echarts

></app-echarts>

<app-footer></app-footer>

echarts.component.html

<div class="container-fluid g-0">
    <app-header (sideNavToggled)="sideNavStatus = $event;"></app-header>

    <main>
        <app-sidebar [sideNavStatus]="sideNavStatus"
                     [ngClass]="{'app-side-nav-open': sideNavStatus}"></app-sidebar>

        <div class="display-area p-3" [ngClass]="{'display-area-shrink': sideNavStatus}">

            <div
                    id="main"
                    style="width: 500px; height: 300px"

            >
            </div >
        </div>
    </main>
</div>

<app-footer></app-footer>
export class EchartsComponent implements OnInit {
  sideNavStatus: boolean = false;
  subscription!: Subscription;


  constructor(private dataService: DataService) {
  }


  ngOnInit(): void {
    
  }
}

I tried to pass methods to the child component through the input but nothing comes out

From your code sample, I'm assuming you're trying to access the EchartsComponent ViewChild in the logs component and pass data to it.

Here's an example of how you can do that, minus some pieces from your sample code for brevity...

class LogsComponent {

  @ViewChild(EchartsComponent)
  echartsComponent: EchartsComponent;

  LoadEcharts(): void {
    const chartDom: HTMLElement = document.getElementById('main') as HTMLElement; // <-- not sure what this is
    const myChart = echarts.init(chartDom);  // <-- not sure what this is

    this.subscription = this.dataService.getLogs().subscribe(data => {
      this.echartsComponent.logs = data;
      // `logs` doesn't exist in the current code for EchartsComponent.
      // You'll need to add it.
    });
  }

}

What I don't see in your EchartsComponent is a logs property to set. If you're using a ViewChild in the parent component, you don't have to use @Input on the ViewChild instance, you have programmatic access to the component and can set properties or call methods.

If you want to use @Input() , you can do that too:

class EchartsComponent {
  @Input()
  logs: Logs[];
}

// logs.component.ts

class LogsComponent {

  LoadEcharts(): void {
    this.subscription = this.dataService.getLogs().subscribe(data => {
      this.logs = data;
    })
  }
}

// logs.component.html

<app-echarts [logs]="logs"></app-echarts>

In this scenario, when the observable for getLogs() emits, the property logs is set to the new value. That value, being a new reference is passed to the child component via its input.

Hope that helps you out.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM