我正在尝试构建绘制图表的angular2组件(使用jquery plot)
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;
}
}
}
组件获取图表&#34;数据&#34; property作为输入参数:
<flot [options]="splineOptions" [dataset]="dataset" height="250px" width="100%"></flot>
到目前为止,我设法使其工作只要&#34;数据集&#34;是静态变量。
this.dataset = [{label: "line1",color:"blue",data:[[1, 130], [3, 80], [4, 160], [5, 159], [12, 350]]}];
我的问题是当数据作为承诺时使它工作:
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]}];
}
}
由于某种原因,数据更改无法投射到&#34; flot&#34;成分
此处链接指向plunk
请帮忙
答案 0 :(得分:2)
问题是
entries => this.dataset[0].data = entries,
因为只更改了绑定值的内部状态,并且Angular2更改检测不会仅查看内容中的值或引用本身。
解决方法是创建具有相同内容的新数组
this._flotService.getFlotEntries().then(
entries => {
this.dataset[0].data = entries;
this.dataset = this.dataset.slice();
},
在您的情况下,可以使用其他事件通知子组件更新已经发生。
答案 1 :(得分:1)
除了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;
}
}
我觉得这是一种更简洁的方法,因为我们不必为了满足/触发角度变化检测而以特定的方式编写代码。但唉,它的效率较低。 (当发生这种情况时,我讨厌它!)
此外,ngOnChanges()
中的代码可以移至ngOnInit()
。
正如Günter已经提到的,ngOnChanges()
未被调用,因为填写数据时dataset
数组引用不会更改。因此Angular不认为任何输入属性发生了变化,因此不会调用ngOnChanges()
。无论是否有任何输入属性更改,ngDoCheck()
始终会被调用每个更改检测周期。
另一个选择是在父组件中使用@ViewChild(FlotCmp)
,它将获得对FlotCmp
的引用。然后,父级可以使用该引用在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;
}
这比ngDoCheck()
效率更高,并且它没有我在上面用ngOnChanges()
方法描述的问题。
但是,如果我使用这种方法,我会稍微修改代码,因为我不喜欢dataset
当前是一个输入属性,但是drawPlot()
获取传入的数据通过函数参数。