我有一个AngularJs应用程序,它从API检索数据并将它们填充到表中。然后,我使用Highcharts根据该表绘制图表。如果我在表中使用静态数据,它工作正常,但是当我通过AJAX更新表时它不起作用。它不会重绘。
指令:
app.directive('highChart', function ($parse) {
return {
link: function(scope, element, attrs) {
scope.$watch('chartConfig', function (newVal) {
if (newVal) {
var props = $parse(attrs.highChart)(scope);
props.chart.renderTo = element[0];
new Highcharts.Chart(props);
}
});
}
};
});
控制器:
appControllers.controller('SummaryController', ['$scope', '$timeout', 'Summaries',
function ($scope, $timeout, Summaries) {
// Request from API
Summaries.get({ table: 'level'}).$promise.then(
// success callback
function(data) {
$scope.levels = data.level[0][today];
$scope.chartConfig = {
data: {
table: document.getElementById('daily-level')
},
chart: {
type: 'column'
},
title: {
text: 'Data extracted from a HTML table in the page'
},
yAxis: {
allowDecimals: false,
title: {
text: 'Units'
}
},
tooltip: {
formatter: function () {
return '<b>' + this.series.name + '</b><br/>' +
this.y + ' ' + this.x;
}
}
};
}
}]);
HTML
<div id="top-chart" high-chart="chartConfig"></div>
它只显示一个空图表。我的表确实由AJAX请求更新。我甚至在指令中检查了console.log(props)
,props.data.table
确实显示了更新的表,但不知何故图表没有重绘。我已经尝试了多种方法来做到这一点,但都归结为相同的结果。目前,我只是使用jQuery超时刷新图表,它可以工作,但这意味着我在控制器内部使用DOM操作。我正在尝试使用指令实现此目的。
答案 0 :(得分:3)
确定。我设法让它发挥作用。我认为问题是,Highcharts不知道这些变化,或者它是否知道变化,那时的DOM还没有完成渲染。这是代码的工作版本。
指令:
app.directive('highchart', function($parse, $timeout) {
return {
restrict: 'E',
template: '<div></div>',
replace: true,
link: function(scope, element, attrs) {
var config = $parse(attrs.config)(scope);
$(element[0]).highcharts(config);
scope.$watch(attrs.watch, function(newVal) {
if (newVal) {
var complete = function (options) {
var chart = $(element[0]).highcharts();
// capture all available series
var allSeries = chart.series;
for (var i = 0; i < allSeries.length; i++) {
allSeries[i].setData(options.series[i].data, false);
}
chart.redraw();
};
// doesn't work without the timeout
$timeout(function() {
Highcharts.data({
table: config.data.table,
complete: complete
});
}, 0);
}
});
}
};
});
在控制器中,我们可以设置配置。
$scope.chartConfig = {
// config here
};
使用它:
<highchart config="chartConfig" watch="levels"></highchart>
属性config
绑定到$scope.chartConfig
,watch
是指令中watch.$scope()
的触发器。当$scope.levels
在控制器中发生变化时,它将重新渲染图表。
我实际上并不喜欢该指令对我现在拥有的watch
属性的依赖性,但我不确定这样做的最佳或其他方法是什么。如果有人有更好的想法,请告诉我。
请注意,这只能将表转换为高图。对于其他人,您可能需要使用其他angularjs highcharts指令。
答案 1 :(得分:1)
在下面的示例中,您可以使用watch更新数据库中的更新数据。它会继续检查新数据并分别进行更改:
app.directive('line',['$compile', function ($compile) {
return {
restrict: 'E',
replace: true,
template: '<div></div>',
scope: {
data: '=',
},
link: function (scope, element) {
scope.lineGraphInstance = Highcharts.chart(element[0],{
chart: {
type: 'spline',
style: {
fontSize: '8px'
},
spacingBottom: scope.data.spacingBottom,
spacingTop: scope.data.spacingTop,
spacingLeft: scope.data.spacingLeft,
spacingRight: scope.data.spacingRight,
},
title: {
text: '',
},
xAxis: {
type: 'datetime',
title: {
text: scope.data.xtitle,
enabled: false
},
labels: {
style: {
fontSize: '8px'
},
autoRotation: 0,
formatter: function () {
var x=this.value;
if (scope.data.hasOwnProperty("dateformat"))
x= Highcharts.dateFormat(scope.data.dateformat, this.value);
if (scope.data.hasOwnProperty("xSuffix"))
x=x+scope.data.xSuffix;
if(scope.data.hasOwnProperty("xPrefix"))
x=scope.data.xPrefix+x;
return x;
},
enabled:scope.data.xtitleEnable
},
tickWidth: 3,
tickLength:scope.data.tickLength,
tickInterval: 3600 * 100
},
yAxis: {
opposite: true,
title: {
text: scope.data.ytitle,
enabled: false
},
min: 0,
labels: {
style: {
fontSize: '10px'
},
formatter: function () {
var y=this.value;
if (scope.data.hasOwnProperty("ySuffix"))
y=y+scope.data.ySuffix;
if(scope.data.hasOwnProperty("yPrefix"))
y=scope.data.yPrefix+y;
return y;
},
},
plotLines: [{
value: scope.data.ucl,
color: '#F39C12',
dashStyle: 'shortdash',
width: 1,
}, {
value: scope.data.lcl,
color: '#F39C12',
dashStyle: 'shortdash',
width: 1,
}]
},
tooltip: {
headerFormat: '<b>{series.name}</b><br>',
pointFormat: '{point.x:%e. %b}: {point.y:.2f} '
},
plotOptions: {
spline: {
marker: {
enabled: true
}
}
},
legend:{
enabled:false
},
series:[{data:scope.data.data,
marker: {
enabled: true,
radius: 2
},
lineWidth: 1
}],
credits: {
enabled: false
},
exporting: { enabled: false
}
});
***scope.$watch('data', function (newValue, oldValue) {
if(newValue && newValue.data){
var graphData=newValue.data[0].data.slice(-5);
scope.lineGraphInstance.series[0].setData(graphData, true);
}
}, true);
}***
};
}]);
答案 2 :(得分:0)
您是否尝试设置工厂,在调用从工厂获取值后,将使用$resource
http://docs.angularjs.org/api/ngResource。$资源内部,然后将其显示在图表中?