Bind array to highcharts data part using Angular Directives - angularjs

I need to bind an array of data to "data" part of highcharts which is embedded in
Angular directives but I don't know how exactly to do that.
This is my controller part which fetches data from repository:
vm.data = [];
function getVmAll(forceRefresh) {
return datacontext.esxservers.getAllWithoutPaging(forceRefresh, vm.vmAllSearchTemp)
.then(function (data) {
vm.data= data;
});
return data;
}
);
}
and here is the template which I use the controller in it:
<section class="mainbar" data-ng-controller="mbVirtualizationOverviewCtrl as vm">
<mb-virtualization-overview-donut-chart value="vm.data"></mb-virtualization-overview-donut-chart>
</section>
and the last but not least one is my directive which I use highcharts settings:
'use strict';
angular.module('app').directive('mbVirtualizationOverviewDonutChart', [
function () {
return {
restrict: "E",
templateUrl: '/app/directives/virtualizationOverview/mbVirtualizationOverviewDonutChartTemplate.html',
scope: {
value : "="
},
link: function (scope, el, attrs) {
scope.chart = Highcharts.chart(el[0], {
chart: {
type: 'pie',
},
title: {
text: scope.innerTitle
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: false
},
showInLegend: true
}
},
series: [{
data: undefined
}]
});
var init = true;
scope.$watch(
function () {
var chart = scope.chart;
if (init && scope.value.length > 0) {
init = false;
scope.value.forEach(function (item, index) {
chart.series[0].data.push(item);
});
}
});
}
};
}
]);

Related

Angular lazy tree

I'm studying angular and trying to write treeview with dynamic load. It has some initial pre-loaded nodes, but many of them have to be loaded by demand.
I write initial tree view here jsfiddle but cannot understand how to implement lazy load.
when I click NodeLazy I want to update treeService.Nodes and this update have to refresh view
when I click any Node I want select this node by bold font and be able get selected from treeService
Sure, I could use one of existing angular tree, but I want to understand how to do this.
var app = angular.module('demo', []);
app.directive("treeView", function() {
return {
restrict: "E",
replace: true,
scope: {
t: "=src"
},
template: "<ul class='ul-node'><tree-branch ng-repeat='c in t.children' src='c'></tree-branch></ul>"
};
});
app.directive("treeBranch", function($compile) {
return {
restrict: "E",
replace: true,
scope: {
b: "=src"
},
template: "<li class='{{b.class_li}}'>{{b.name}}</li>",
controller: function($scope) {
var has_children = angular.isArray($scope.b.children);
$scope.b.class_li = has_children ? "li-node" : "li-leaf";
},
link: function(scope, element, attrs) {
var has_children = angular.isArray(scope.b.children);
if (has_children) {
element.append('<tree-view src="b"></tree-view>');
$compile(element.contents())(scope);
}
element.on("click", function(event) {
console.log("click|" + scope.b.name);
event.stopPropagation();
if (has_children) {
element.toggleClass("ul-collapsed");
}
});
}
};
});
app.service("treeService", function() {
var nodes = {
children: [
{ name: "Node_1",
children: [
{ name: "Node_1.1",
children: [{ name: "Leaf_1" }, { name: "Leaf_2" }] },
{ name: "NodeLazy_1.2", }] },
{ name: "NodeLazy_2", }]
};
return {
Nodes : nodes
};
});
app.controller("ctrl", function($scope, treeService) {
$scope.nodes = treeService.Nodes;
});

Highcharts can not update diagram using angular.js

I'm working on a project which uses Highcharts and Angularjs and fetches data using SignalR. The problem is the pie chart initializes correctly but can not update the diagram with the data comes from server. here is my code:
'use strict';
angular.module('mbCharts').directive('mbGauge', [
'mbWebMetricsService',
function (mbWebMetricsService) {
return {
//
// scope is inherited from the widget using this directive
//
templateUrl: '/ext-modules/mbCharts/mbGaugeTemplate.html',
link: function (scope, el, attrs) {
Highcharts.chart(el[0], {
chart: {
type: 'pie'
},
title: {
text: scope.title
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '<b>{point.name}</b>: {point.percentage:.1f} %'
}
}
},
series: [{
data: [{
name: "Microsoft Internet Explorer",
y: 100
}, {
name: "Chrome",
y: 0,
sliced: true,
selected: true
}]
}]
});
// locate the widget showing this gauge
var widget = el.closest('.gridster-item');
// monitor the widget's size
widget.resize(function () {
//if (scope.chart != null) {
// scope.chart.chartWidth = widget.width();
// scope.chart.chartHeight = widget.height();
//}
});
//scope.title = mbWebMetricsService.getTitleForMetric(scope.metric);
scope.title = "CPU percentage";
scope.initialized = false;
scope.$on('mbWebMetricsService-received-data-event', function (evt, data) {
var val = Math.round(data[scope.metric]);
scope.chart.series[0].data[0].y = val;
scope.chart.series[0].data[1].y = 100 - val;
});
}
};
}
]);
The problem is how you want to update data. It's not about changing options in chart object, but using proper API. To update points, use chart.series[index].data[pointsIndex].update().
So in your case, first store a chart object:
var myChart = new Highcharts.Chart(el[0], { ... });
Then update points:
scope.$on('mbWebMetricsService-received-data-event', function (evt, data) {
var val = Math.round(data[scope.metric]);
myChart.series[0].data.update(val);
myChart.series[0].data.update(100 - val);
});

Link function of Directive is not being called

I have a scenario where I need to show a pie-chart in a popup modal (used ui-bootstrap modal). I used c3.js for my pie-chart requirement (inside a directive).
The pie-chart is not loading inside the pop up. But to my surprise when I tried to debug the issue when I opened the console it is loading. When I re-size the window it is loading.
How can i fix this issue?
'use strict';
angular.module('App')
.directive('pieChartDirective', function() {
return {
restrict: 'A',
scope: {
chartdata: '=',
},
link: function(scope, elem, attrs) {
var chart = c3.generate({
bindto: '#chart',
data: {
columns: [
['Javascript', scope.chartdata.Javascript],
['HTML', scope.chartdata.HTML],
['Css', scope.chartdata.Css],
['Angular', scope.chartdata.Angular],
['Bootstrap', scope.chartdata.Bootstrap],
['Jquery', scope.chartdata.Jquery],
['Communication', scope.chartdata.Communication]
],
type: 'pie',
},
legend: {
show: false
},
tooltip: {
format: {
value: function(value, ratio, id, index) {
return value;
}
}
}
});
}
};
});
Html:
<div pie-chart-directive chartdata="oChartData">
<div id="chart"></div>
</div>
Are you shure, that you include your directive properly in your html code as
<div pie-chart-directive></div>
Maybe you have to change your restriction to 'E' to use your directive as a tag elment
<pie-chart-directive chartdata="myData"></pie-chart-directive>
The reason could be, that at the moment you try to generate the chart, your '#chart' div isn't yet present in the dom tree. Therefore you have to resize to trigger a new draw. Try to wait until the dom is loaded
$('#chart').ready(function() {
var chart = c3.generate({
bindto: '#chart',
data: {
columns: [
['Javascript', scope.chartdata.Javascript],
['HTML', scope.chartdata.HTML],
['Css', scope.chartdata.Css],
['Angular', scope.chartdata.Angular],
['Bootstrap', scope.chartdata.Bootstrap],
['Jquery', scope.chartdata.Jquery],
['Communication', scope.chartdata.Communication]
],
type: 'pie',
},
legend: {
show: false
},
tooltip: {
format: {
value: function(value, ratio, id, index) {
return value;
}
}
}
});
});
I got it by giving size property:
link: function(scope, elem, attrs) {
var chart = c3.generate({
bindto: '#chart',
size: {
width:400,
height:350
},
data: {
columns: [
['Javascript', scope.chartdata.Javascript],
['HTML', scope.chartdata.HTML],
['Css', scope.chartdata.Css],
['Angular', scope.chartdata.Angular],
['Bootstrap', scope.chartdata.Bootstrap],
['Jquery', scope.chartdata.Jquery],
['Communication', scope.chartdata.Communication]
],
type: 'pie',
},
legend: {
show: false
},
tooltip: {
format: {
value: function(value, ratio, id, index) {
return value;
}
}
}
});
}

Angularjs directive scope seems not binding to value

Please spare me if this is a beginner type of question. I'm playing Highcharts.js with Angular.js, but it's seems like directive scope is not binding to value. Below are my codes.
HTML - but it's working inside this expressions {{xaxis}} {{seriesdata}}
<div class="container" ng-controller='chartController'>
<div class="row">
<div class="col-md-6">
<line-chart xaxis='xaxis' seriesdata='seriesdata'></line-chart>
{{xaxis}}
{{seriesdata}}
</div>
<div class="col-md-6">
<bar-chart options='pieOptions'></bar-chart>
</div>
</div>
</div>
directive.js
(function() {
'use strict';
angular
.module('chart')
.directive('lineChart', lineChartDirective);
/* #ngInject */
function lineChartDirective() {
return {
restrict: 'E',
replace: true,
template: '<div></div>',
scope: {
xaxis: '=xaxis',
seriesdata: '=seriesdata'
},
link: function(scope, element) {
Highcharts.chart(element[0], {
chart: {
type: 'spline',
zoomType: 'x'
},
plotOptions: {
line: {
dataLabels: {
enabled: true
}
}
},
title: {
text: 'Profit Ratio by Month'
},
xAxis: {
categories: scope.xaxis
},
yAxis: {
title: {
text: 'Profit %'
}
},
series: [
{
name: 'Total',
data: scope.seriesdata
}
]
});
}
}
}
})();
service.js
(function() {
'use strict';
angular
.module('chart')
.factory('chartData', chartDataFactory);
chartDataFactory.$inject = ['$http'];
/* #ngInject */
function chartDataFactory($http) {
function getData() {
return $http.get('../../data/sampleData.json').then(function(result) {
return result.data;
})
}
return {
getData: getData
}
}
})();
controller.js
(function() {
'use strict';
angular
.module('chart')
.controller('chartController', chartController);
chartController.$inject = ['$scope', 'chartData', 'lodash'];
/* #ngInject */
function chartController($scope, chartData, lodash) {
var vm = this;
chartData.getData().then(function(data) {
$scope.chartData = data;
$scope.xaxis = data.SEO[0]["SEO-MOD-001"]["SEO-END-001"];
$scope.seriesdata = data.SEO[0]["SEO-MOD-001"]["SEO-END-002"];
console.log($scope.xaxis);
console.log($scope.seriesdata);
});
$scope.pieOptions = {
chart: {
type: 'column'
},
title: {
text: 'Projects'
},
xAxis: {
categories: ['Noreil', 'Ken', 'Alfie', 'Francis']
},
yAxis: {
title: {
text: 'Completed Projects'
}
},
series: [
{
name: 'Quarter 1',
data: [23, 11, 34, 26]
},
{
name: 'Quarter 2',
data: [14, 20, 26, 30]
}
]
}
}
})();
When the directive link function gets executed, you don't have data yet. So try following in link function:
var unwatch = scope.$watch('[xaxis, seriesdata]', function (results) {
if (results[0] && results[1]) {
init();
unwatch();
}
}, true);
function init() {
// Highcharts.chart(element[0], { ...
}

Angular material Treeview collapse/expand check box not working

Angular Material Tree view Checkbox is working fine when i try to collapse/expand first time and checked whether on Parent Node or Child Node, but it is not working when i try to Checked the different node (i.e.Child Node) on second time. I use custom directive to achieve Tree View functionality. Below is my Code.
Custom Directive
NFSModule.directive('nfsTree', function () {
return {
restrict: 'E',
replace: true,
scope: {
tree: '=source',
},
template: '<nfs-node ng-repeat="c in tree.children" cnode="c"></nfs-node>'
};
});
NFSModule.directive('nfsNode', function ($compile) {
return {
restrict: 'E',
replace: true,
scope:{
node: '=cnode'
},
template: '<li><span ng-click="toggleVisibility(node)"> {{ ( node.childrenVisibility && node.children.length ) ? "+" : "-" }}</span>' +
'<nfs-tree-checkbox ng-model="node.checked" ng-click="checkNode(node)"><span ng-bind="node.name"></span></nfs-tree-checkbox></li>', // HTML for a single node.
link: function (scope, element) {
/*
* Here we are checking that if current node has children then compiling/rendering children.
* */
if (scope.node && scope.node.children && scope.node.children.length > 0) {
scope.node.childrenVisibility = true;
var childNode = $compile('<ul ng-if="!node.childrenVisibility"><nfs-tree source="node" ></nfs-tree></ul>')(scope);
element.append(childNode);
} else {
scope.node.childrenVisibility = false;
}
},
controller: ["$scope", function ($scope) {
// This function is for just toggle the visibility of children
$scope.toggleVisibility = function (node) {
if (node.children) {
node.childrenVisibility = !node.childrenVisibility;
}
};
// Here We are marking check/un-check all the nodes.
$scope.checkNode = function (selectednode) {
if (selectednode.checked != undefined) {
var has_child = angular.isArray(selectednode.children);
if (has_child = true)
{
checkChildren(selectednode);
}
}
function checkChildren(c) {
angular.forEach(c.children, function (c) {
c.checked = selectednode.checked;
});
}
};
}]
};
});
NFSModule.directive('nfsTreeCheckbox', function () {
return {
restrict: 'E',
replace: true,
transclude: true,
scope: {
name: '#',
ngModel: '=',
ngClick: '=',
ngDisabled: '=',
label: '#'
},
template: function (elem, attr) {
return '<md-input-container class="md-inline" style="height:10px !important; margin-top:-5px; !important; margin-left:5px !important;">' +
'<md-checkbox ng-model="ngModel" ng-click="ngClick" ng-disabled="ngDisabled" aria-label="{{label}}" class="md-primary">' +
'<ng-transclude></ng-transclude>' +
' </md-checkbox>' +
'</md-input-container>'
}
};
});
$SCOPE
$scope.location = {
children:
[
{
name: 'Europe',
children: [
{
name: 'Italy',
children: [
{
name: 'Rome'
},
{ name: 'Milan' }
]
},
{ name: 'Spain' }
]
},
{
name: 'South America',
children: [
{ name: 'Brasil' },
{ name: 'Peru' }
]
}
]
};
HTML
<ul >
<nfs-tree source="location"></nfs-tree>
</ul>

Resources