[英]how to project data change into child component with angular2?
i'm trying to build angular2 component which draws chart (using jquery plot) 我正在尝试构建绘制图表的angular2组件(使用jquery图)
import {Component, ElementRef, Input, OnChanges} from 'angular2/core';
@Component({
selector: 'flot',
template: `<div>loading</div>`
})
export class FlotCmp implements OnChanges{
private width = '100%';
private height = 220;
static chosenInitialized = false;
@Input() private options: any;
@Input() private dataset:any;
@Input() private width:string;
@Input() private height:string;
constructor(public el: ElementRef) {}
ngOnChanges() {
if(!FlotCmp.chosenInitialized) {
let plotArea = $(this.el.nativeElement).find('div').empty();
plotArea.css({
width: this.width,
height: this.height
});
$.plot( plotArea, this.dataset, this.options);
FlotCmp.chosenInitialized = true;
}
}
}
Component getting chart "data" property as input parameter: 将图表“data”属性作为输入参数的组件:
<flot [options]="splineOptions" [dataset]="dataset" height="250px" width="100%"></flot>
So far i managed to make it work as long as "dataset" is static variable. 到目前为止,只要“dataset”是静态变量,我就设法使其工作。
this.dataset = [{label: "line1",color:"blue",data:[[1, 130], [3, 80], [4, 160], [5, 159], [12, 350]]}];
My problem is to make it work when data came as a promise: 我的问题是当数据作为承诺时使其工作:
export class App implements OnInit {
private dataset:any;
public entries;
getEntries() {
this._flotService.getFlotEntries().then(
entries => this.dataset[0].data = entries,
error => this.errorMessage = <any>error);
}
ngOnInit() {
this.getEntries()
}
constructor(private _flotService:FlotService) {
this.name = 'Angular2'
this.splineOptions = {
series: {
lines: { show: true },
points: {
radius: 3,
show: true
}
}
};
this.dataset = [{label: "line1",color:"blue",data:null]}];
}
}
For some reason data change cannot project to "flot" component 由于某种原因,数据更改无法投射到“flot”组件
here is link to plunk 这里是plunk的链接
Please help 请帮忙
The problem is 问题是
entries => this.dataset[0].data = entries,
because only the inner state of the bound value is changed and Angular2 change detection doesn't observe the content only the value or reference itself. 因为只有绑定值的内部状态发生了变化,Angular2变化检测才会观察到内容只有值或引用本身。
A workaround would be to create a new array with the same content 解决方法是创建具有相同内容的新阵列
this._flotService.getFlotEntries().then(
entries => {
this.dataset[0].data = entries;
this.dataset = this.dataset.slice();
},
In your case an additional event could work that notifies the child component that updates have happended. 在您的情况下,可以使用其他事件通知子组件更新已经发生。
Besides Günter's answer, another option is to implement your own change detection inside ngDoCheck()
which will be called when your data comes back from the server: 除了Günter的答案,另一个选择是在
ngDoCheck()
实现你自己的变化检测,当你的数据从服务器返回时将被调用:
ngDoCheck() {
if(this.dataset[0].data !== null && !this.dataPlotted) {
console.log('plotting data');
let plotArea = $(this.el.nativeElement).find('div').empty();
$.plot( plotArea, this.dataset, this.options);
this.dataPlotted = true;
}
}
I feel this is a cleaner approach, since we don't have to write code a specific way just to satisfy/trigger Angular change detection. 我觉得这是一种更简洁的方法,因为我们不必为了满足/触发角度变化检测而以特定的方式编写代码。 But alas, it is less efficient.
但唉,它的效率较低。 (I hate it when that happens!)
(当发生这种情况时,我讨厌它!)
Also, the code you have in ngOnChanges()
can be moved to ngOnInit()
. 此外,您在
ngOnChanges()
的代码可以移动到ngOnInit()
。
As Günter already mentioned, ngOnChanges()
isn't called because the dataset
array reference doesn't change when you fill in your data. 正如Günter已经提到的那样,不会调用
ngOnChanges()
因为填充数据时dataset
数组引用不会更改。 So Angular doesn't think any input properties changed, so ngOnChanges()
isn't called. 因此Angular不认为任何输入属性发生了变化,因此不会调用
ngOnChanges()
。 ngDoCheck()
is always called every change detection cycle, whether or not there are any input property changes. 无论是否有任何输入属性更改,都会在每个更改检测周期中调用
ngDoCheck()
。
Yet another option is to use @ViewChild(FlotCmp)
in the parent component, which will get a reference to FlotCmp
. 另一种选择是在父组件中使用
@ViewChild(FlotCmp)
,它将获得对FlotCmp
的引用。 The parent could then use that reference to call some method, say drawPlot()
, on FlotCmp
to draw/update the plot when the data arrives. 然后,家长可以使用参考调用一些方法,比如说
drawPlot()
在FlotCmp
绘制/当数据到达时更新的情节。
drawPlot(dataset) {
console.log('plotting data', dataset);
let plotArea = $(this.el.nativeElement).find('div').empty();
$.plot( plotArea, dataset, this.options);
this.dataset = dataset;
}
This is more efficient than ngDoCheck()
, and it doesn't have the issue I described above with the ngOnChanges()
approach. 这比
ngDoCheck()
更有效,它没有我上面用ngOnChanges()
方法描述的问题。
However, if I were to use this approach, I would rework the code somewhat, since I don't like how dataset
is currently an input property, but then drawPlot()
gets the data passed in via a function argument. 但是,如果我使用这种方法,我会稍微重做代码,因为我不喜欢
dataset
当前是一个输入属性,但是drawPlot()
获取通过函数参数传入的数据。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.