如何在组件之间共享数据并将其提供给绘图图
How to share data between components and provide it for a plotly chart
让我先解释一下我项目中的工作部分是什么:
dataframe.component
:按钮正在发出调用函数 Initdf()
的事件,该函数会启动从我的后端 API 检索 JSON 数据的服务。我从该数据映射两个值并将它们分配给数组。 dfClose
和 dfDateTime
.
有了这两个数组,我想在 plotly1.component
中提供 plotly.js
图表
我正在尝试实现具有 @Input()
和 @Output()
属性的组件之间的数据共享。
什么不起作用:
在我的 plotly1.component 中,我导入了 onChanges 方法来监听数据的更新(当按钮被点击时),但是我收到大量重复的错误信息:
core.mjs:6485 ERROR TypeError: Cannot read properties of undefined (reading 'data')
我无法完成 onChanges 方法,因为 angular 文档对我来说不够详细。我一个人无法自拔。
dataframe.component.ts:
import { Component, OnInit, Output } from '@angular/core';
import { RestServiceDfinit } from '../../services/rest-df-init.service';
import { DfIndicatorService } from '../../services/rest-df-indicator.service';
import {Plotly1Component} from '../plotly1/plotly1.component';
@Component({
selector: 'app-dataframe',
templateUrl: './dataframe.component.html',
styleUrls: ['./dataframe.component.scss']
})
export class DataframeComponent implements OnInit {
df_array: any = [];
tabVal:any = [];
tabKey:any = [];
df_standard_tab_order: any;
toggleAdd: boolean = true;
toggleDelete: boolean = true;
@Output() dfClose:any;
@Output() dfDateTime:any;
constructor(private restService: RestServiceDfinit, private indicatorService: DfIndicatorService) {}//, private plotly: Plotly1Component) {}
ngOnInit(): void { }
Initdf() {
this.restService.postTickerGetDf().subscribe((response) => {
this.df_array = response;
this.dfClose = this.df_array.map((x: any) => x.Close);
this.dfDateTime = this.df_array.map((x: any) => x.DateTime);
.....
plotly1.component.ts:
import { Component, OnInit, Input, OnChanges } from '@angular/core';
import {Plotly1Service} from '../../services/plotly1.service'
import {Observable} from 'rxjs'
@Component({
selector: 'app-plotly1',
template: '<plotly-plot [data]="graph.data" [layout]="graph.layout"></plotly-plot>'
})
export class Plotly1Component implements OnChanges {
public graph:any;
@Input() dfClose:any;
@Input() dfDateTime:any;
constructor(private plotlyService: Plotly1Service) { }
ngOnChanges(changes: SimpleChanges): void {
this.fill_data();
}
fill_data() {
this.graph = {
data: [
{ x: this.dfDateTime, y: this.dfClose, type: 'scatter', mode: 'lines', marker: {color: 'blue'} },
],
layout: {width: 1320, height: 600, title: 'test Plot'}}}}
使用 onChanges 是否正确?如何完成?
更新:我跳过了 plotly.component 进行测试,并尝试从 setData
in dataframe.component.ts in a div
中获取数据:
Initdf() {
this.restService.postTickerGetDf().subscribe((response) => {
this.df_array = response;
const close = response.map(x => x.Close);
const dateTime = response.map(x => x.DateTime);
this.mappedData.emit({
dfClose: close,
dfDateTime: dateTime
});
this.setData(this.mappedData);
setData(mappedData:any) {
this.dfClose = mappedData.dfClose;
this.dfDateTime = mappedData.dfDateTime;
this.graph = {
data: [
{ x: this.dfDateTime, y: this.dfClose, type: 'scatter', mode: 'lines', marker: {color: 'blue'} },
],
layout: {width: 1320, height: 600, title: 'test Plot'}}
在 dataframe.component.html 我尝试了这些变体:
<div (mappedData)="setData($event)">{{graph}}</div>
<div (mappedData)="setData($event)">{{mappedData}}</div>
<div >{{graph}}</div>
<div >{{mappedData}}</div>
同样不行。在最好的情况下,我看到 [object Object]
我认为您不了解@Input() 和@Output() 工作流程。
@Output() 它是一个 EventEmitter,它必须发出一个值才能在 parent 组件上接收它。你甚至不需要两个输出。您应该使用一个根据您的需要发出 object 的输出。
// in your child
@Output mappedData = new EventEmitter();
然后在你的函数中你正在做类似的事情:
// in your child Initdf() function
const close = response.map(x => x.Close);
const dateTime = response.map(x => x.DateTime);
this.mappedData.emit({
dfClose: close,
dfDateTime: dateTime
});
然后您将在 parent 组件中捕获这些事件。
// in your parent html file
<app-dataframe (mappedData)="setData($event)></app-dataframe
然后在您的 parent 组件中,您可以使用数据完成您的工作。
// in your parent ts file
setData(mappedData) {
// here you have access to mappedData.dfClose and mappedData.dfDateTime
}
其次,你应该开始使用类型而不是那么多'any'。防止错误要容易得多。
这就是您所需要的。您可以删除这些@Input。您不需要它们,因为您是通过 child.
的 @Output 获取数据的
我自己找到了解决方案。它很符合我最初的想法,即使用 OnChanges
生命周期钩子。
数据框组件 ts:
Initdf() {
this.restService.postTickerGetDf().subscribe((response) => {
this.df_array = response;
数据帧html:
<app-plotly1 [df_array]="df_array"></app-plotly1>
plotly1 组件 ts:
@Input() df_array:any;
ngOnChanges(changes: SimpleChanges): void {
this.dfClose = this.df_array.map((x: any) => x.Close);
this.dfDateTime = this.df_array.map((x: any) => x.DateTime);
让我先解释一下我项目中的工作部分是什么:
dataframe.component
:按钮正在发出调用函数 Initdf()
的事件,该函数会启动从我的后端 API 检索 JSON 数据的服务。我从该数据映射两个值并将它们分配给数组。 dfClose
和 dfDateTime
.
有了这两个数组,我想在 plotly1.component
plotly.js
图表
我正在尝试实现具有 @Input()
和 @Output()
属性的组件之间的数据共享。
什么不起作用:
在我的 plotly1.component 中,我导入了 onChanges 方法来监听数据的更新(当按钮被点击时),但是我收到大量重复的错误信息:
core.mjs:6485 ERROR TypeError: Cannot read properties of undefined (reading 'data')
我无法完成 onChanges 方法,因为 angular 文档对我来说不够详细。我一个人无法自拔。
dataframe.component.ts:
import { Component, OnInit, Output } from '@angular/core';
import { RestServiceDfinit } from '../../services/rest-df-init.service';
import { DfIndicatorService } from '../../services/rest-df-indicator.service';
import {Plotly1Component} from '../plotly1/plotly1.component';
@Component({
selector: 'app-dataframe',
templateUrl: './dataframe.component.html',
styleUrls: ['./dataframe.component.scss']
})
export class DataframeComponent implements OnInit {
df_array: any = [];
tabVal:any = [];
tabKey:any = [];
df_standard_tab_order: any;
toggleAdd: boolean = true;
toggleDelete: boolean = true;
@Output() dfClose:any;
@Output() dfDateTime:any;
constructor(private restService: RestServiceDfinit, private indicatorService: DfIndicatorService) {}//, private plotly: Plotly1Component) {}
ngOnInit(): void { }
Initdf() {
this.restService.postTickerGetDf().subscribe((response) => {
this.df_array = response;
this.dfClose = this.df_array.map((x: any) => x.Close);
this.dfDateTime = this.df_array.map((x: any) => x.DateTime);
.....
plotly1.component.ts:
import { Component, OnInit, Input, OnChanges } from '@angular/core';
import {Plotly1Service} from '../../services/plotly1.service'
import {Observable} from 'rxjs'
@Component({
selector: 'app-plotly1',
template: '<plotly-plot [data]="graph.data" [layout]="graph.layout"></plotly-plot>'
})
export class Plotly1Component implements OnChanges {
public graph:any;
@Input() dfClose:any;
@Input() dfDateTime:any;
constructor(private plotlyService: Plotly1Service) { }
ngOnChanges(changes: SimpleChanges): void {
this.fill_data();
}
fill_data() {
this.graph = {
data: [
{ x: this.dfDateTime, y: this.dfClose, type: 'scatter', mode: 'lines', marker: {color: 'blue'} },
],
layout: {width: 1320, height: 600, title: 'test Plot'}}}}
使用 onChanges 是否正确?如何完成?
更新:我跳过了 plotly.component 进行测试,并尝试从 setData
in dataframe.component.ts in a div
中获取数据:
Initdf() {
this.restService.postTickerGetDf().subscribe((response) => {
this.df_array = response;
const close = response.map(x => x.Close);
const dateTime = response.map(x => x.DateTime);
this.mappedData.emit({
dfClose: close,
dfDateTime: dateTime
});
this.setData(this.mappedData);
setData(mappedData:any) {
this.dfClose = mappedData.dfClose;
this.dfDateTime = mappedData.dfDateTime;
this.graph = {
data: [
{ x: this.dfDateTime, y: this.dfClose, type: 'scatter', mode: 'lines', marker: {color: 'blue'} },
],
layout: {width: 1320, height: 600, title: 'test Plot'}}
在 dataframe.component.html 我尝试了这些变体:
<div (mappedData)="setData($event)">{{graph}}</div>
<div (mappedData)="setData($event)">{{mappedData}}</div>
<div >{{graph}}</div>
<div >{{mappedData}}</div>
同样不行。在最好的情况下,我看到 [object Object]
我认为您不了解@Input() 和@Output() 工作流程。 @Output() 它是一个 EventEmitter,它必须发出一个值才能在 parent 组件上接收它。你甚至不需要两个输出。您应该使用一个根据您的需要发出 object 的输出。
// in your child
@Output mappedData = new EventEmitter();
然后在你的函数中你正在做类似的事情:
// in your child Initdf() function
const close = response.map(x => x.Close);
const dateTime = response.map(x => x.DateTime);
this.mappedData.emit({
dfClose: close,
dfDateTime: dateTime
});
然后您将在 parent 组件中捕获这些事件。
// in your parent html file
<app-dataframe (mappedData)="setData($event)></app-dataframe
然后在您的 parent 组件中,您可以使用数据完成您的工作。
// in your parent ts file
setData(mappedData) {
// here you have access to mappedData.dfClose and mappedData.dfDateTime
}
其次,你应该开始使用类型而不是那么多'any'。防止错误要容易得多。 这就是您所需要的。您可以删除这些@Input。您不需要它们,因为您是通过 child.
的 @Output 获取数据的我自己找到了解决方案。它很符合我最初的想法,即使用 OnChanges
生命周期钩子。
数据框组件 ts:
Initdf() {
this.restService.postTickerGetDf().subscribe((response) => {
this.df_array = response;
数据帧html:
<app-plotly1 [df_array]="df_array"></app-plotly1>
plotly1 组件 ts:
@Input() df_array:any;
ngOnChanges(changes: SimpleChanges): void {
this.dfClose = this.df_array.map((x: any) => x.Close);
this.dfDateTime = this.df_array.map((x: any) => x.DateTime);