I'm trying to use jQuery Sparkline charts with Angularjs. I have multiple charts to display, so I've decided to create a function in the controller and call it for each chart(directive).
JS
controller
.controller('sparklineCtrl', [function(){
this.sparklineBar = function(id, values, height, barWidth, barColor, barSpacing) {
$('.'+id).sparkline(values, {
type: 'bar',
height: height,
barWidth: barWidth,
barColor: barColor,
barSpacing: barSpacing
})
}
}])
directive
.directive('sparklineBar', function(){
return {
restrict: 'A',
scope: {
slBar: '&'
},
link: function(scope, element) {
scope.slBar('stats-bar', [6,4,8,6,5,6,7,8,3,5,9,5,8,4,3,6,8], '45px', 3, '#fff', 2);
}
}
})
HTML
<div data-ng-controller="sparklineCtrl as spctrl">
<div class="chart" id="stats-bar" data-sparkline-bar data-sl-bar="spctrl.sparklineBar()"></div>
</div>
Running the above code there is no error in browser console but it's not rendering the chart at all. I don't know what is wrong in my code. When I try to place function's code directly inside directive, it's working.
.directive('sparklineBar', function(){
return {
restrict: 'A',
link: function(scope, element) {
$('#stats-bar').sparkline([6,4,8,6,5,6,7,8,3,5,9,5,8,4,3,6,8], {
type: 'bar',
height: 45,
barWidth: 3,
barColor: '#fff',
barSpacing: 2
})
}
}
})
I don't want to use the above way as I need multiple charts. Please help me fix this using controller functions.
It is better to move the function logic into service/factory then using Injection to be used in your directive.
Example:
app.factory('sparkService', function () {
var ss = {} ;
ss.slBar= function(id, values, height, barWidth, barColor, barSpacing) {
$('.'+id).sparkline(values, {
type: 'bar',
height: height,
barWidth: barWidth,
barColor: barColor,
barSpacing: barSpacing
});
};
return ss;
}
While in directive
.directive('sparklineBar', ['sparkService',function(sparkService){
return {
restrict: 'A',
scope: {
slBar: '&'
},
link: function(scope, element) {
sparkService.slBar('stats-bar', [6,4,8,6,5,6,7,8,3,5,9,5,8,4,3,6,8], '45px', 3, '#fff', 2);
}
}]);
Related
I am using easypiecharts in angular. I am trying to add an attribute(data-statusId) to the markup and use that in js to change the color of the progress bar. When data-opt= 8, it should turn to grey or else should be green.But my condition is failing all the time because, greyBar value is returned as "undefined" all the time.
Attached the screenshots for reference. I need to access the value under dataset for "opt".
.directive('isLoaded', function () {
return {
restrict: 'A', //Attribute type
link: function (scope, elements, arguments) {
ProgressMeter($('#inprogress-card').find('.progress-icon'), false);
}
}
});
function Meter($ele, isPopUp) {
setTimeout(function () {
if (isPopUp && $ele.find('canvas').length > 0) {
$ele.data('easyPieChart').update(0);
$ele.data('easyPieChart').update($ele.attr('data-percent'));
}
else {
$ele.easyPieChart({
easing: 'easeOutBounce',
scaleColor: false,
lineWidth: 4,
trackColor: '#CCCCCC',
barColor: function () {
var greyBar = $ele.data('opt');
if (typeof(greyBar) != 'undefined')
return '#44AD3A'
else
return '#989798'
},
lineCap: 'round',
onStep: function (from, to, percent) {
}
});
}
}, 100);
}`
HTML:
<div class="progress-icon" data-opt="{{list.Status}}" data-percent=" {{ (20/30)* 100)}} ">
For some how, I was facing issues with the data-opt, . I used isolated-scope instead.
I added "opt={{list.Status}}" to the HTML view and then in js, i added scope: {opt:'#'}. And it worked!!
HTML,
<div ng-click="openModal($event,list,id)" opt="{{list.Status}}">
<div class="progress-icon" data-percent=" {{ (20/30)* 100)}} ">
</div>
js:
.directive('isLoaded', function () {
return {
restrict: 'A',
scope:{
opt:'#' //*Added this*
}
link: function (scope, elements, arguments) {
if(scope.opt!=8)
ProgressMeter($('#inprogress-card').find('.progress-icon'), false,'#44AD3A');
else
ProgressMeter($('#inprogress-card').find('.progress-icon'), false,'#989798');
}
}
});
function Meter($ele, isPopUp) {
setTimeout(function () {
if (isPopUp && $ele.find('canvas').length > 0) {
$ele.data('easyPieChart').update(0);
$ele.data('easyPieChart').update($ele.attr('data-percent'));
}
else {
$ele.easyPieChart({
easing: 'easeOutBounce',
scaleColor: false,
lineWidth: 4,
trackColor: '#CCCCCC',
barColor: function () {
var greyBar = $ele.data('opt');
if (typeof(greyBar) != 'undefined')
return '#44AD3A'
else
return '#989798'
},
lineCap: 'round',
onStep: function (from, to, percent) {
}
});
}
}, 100);
}`
topology.controller.js
define(['app/topology/topology.module','app/topology/topology.services', 'app/topology/topology.directives'], function(topology, service) {
topology.controller('TopologyCtrl', ['$scope', '$rootScope', '$location', 'NetworkTopologySvc' , function ($scope, $rootScope, $location, NetworkTopologySvc) {
$rootScope['section_logo'] = 'assets/images/logo_topology.gif';
var graphRenderer = null;
$scope.createTopology = function() {
NetworkTopologySvc.getNode("flow:1", function(data) {
$scope.topologyData = data;
});
};
$scope.createTopology();
}]);
});
topology.directives.js
define(['app/topology/topology.module', 'vis'], function(topology, vis) {
topology.directive('topologySimple', function() {
// constants
var width = 800,
height = 800;
return {
restrict: 'E',
scope: {
topologyData: '='
},
link: function($scope, iElm, iAttrs, controller, $window, $location) {
$scope.$watch('topologyData', function (ntdata) {
if(ntdata){
// visinit(inNodes, inEdges, container, inOptions) {
var inNodes = $scope.topologyData.nodes;
var inEdges = $scope.topologyData.links;
var container = iElm[0];
// legend moved to topology controller
var data = {
nodes: inNodes,
edges: inEdges
};
var color = '#66FFFF',
hl = '#0066FF',
hover = '#33CC33',
BLACK = '#2B1B17';
var options =
{
width: '100%',
height: '750px',
nodes: {
widthMin: 20,
widthMax: 64,
fontColor: BLACK
},
edges: {
length: 80,
color: {
color: '#070707',
highlight: hl,
hover: hover
}
},
physics: {
barnesHut: {
gravitationalConstant: -7025
}
},
hover: true,
groups: {
'switch': {
shape: 'image',
image: 'assets/images/Device_switch_3062_unknown_64.png'
},
'host': {
shape: 'image',
image: 'assets/images/Device_pc_3045_default_64.png'
}
},
keyboard:true,
tooltip: {
delay: 300,
fontColor: "black",
fontSize: 14, // px
fontFace: "verdana",
color: {
border: "#666",
background: "#FFFFC6"
}
}
};
var graph = new vis.Graph(container, data, options);
return graph.on("click", function (params) {
console.log(params);
});
}
});
}
};
});
});
How to send the data received into 'params' to controller.
The params contains :
"nodes": [1,2],
"links": [3,4]
Please help me with this.
Any help would be appreciated.
You have several ways to do so.
using service or factory, but you can also pass data using $rootScope - not a good practice. simple $rootScope example:
in directive:
$rootScope.nodes = nodes;
and you can simple access them at your controller:
I am trying to integrate angular with joint js.I have wrapped the joint js content within angular directive but for some reasons, the code is not working.
view contains:
<joint-diagram graph="graph" width="width" height="height" grid-size="1" />
Directive:
app.directive('jointDiagram', [function () {
var directive = {
link: link,
restrict: 'E',
scope: {
height: '=',
width: '=',
gridSize: '=',
graph: '=',
}
};
return directive;
function link(scope, element, attrs) {
var diagram = newDiagram(scope.height, scope.width, scope.gridSize, scope.graph, element[0]);
}
function newDiagram(height, width, gridSize, graph, targetElement) {
var paper = new joint.dia.Paper({
el: targetElement,
width: width,
height: height,
gridSize: gridSize,
model: graph,
});
return paper;
}
}]);
graph,width and height are passed via a controller.Directive is only rendering the paper object without any nodes(cells)c passed via graph object.But when I print the paper object,it does contain graph object having nodes.what could be the reason behind this.
I'm not 100% certain of the underlying cause of this but since you're adding items to the graph before you create your Paper instance, they aren't drawn. You can use graph.resetCells() to trigger the redraw. For example, using the Hello World example provided in JointJS;
// Create an empty Graph instance and assign to the Paper instance
var graph = new joint.dia.Graph,
paper = new joint.dia.Paper({
el: element[0],
width: scope.width,
height: scope.height,
model: graph,
gridSize: scope.gridSize
}),
cells = [];
var rect = new joint.shapes.basic.Rect({
position: { x: 100, y: 30 },
size: { width: 100, height: 30 },
attrs: { rect: { fill: 'blue' }, text: { text: 'A Box', fill: 'white' } }
});
var rect2 = rect.clone();
rect2.translate(300);
var link = new joint.dia.Link({
source: { id: rect.id },
target: { id: rect2.id }
});
cells.push(rect, rect2, link);
// Now refresh the graph to ensure the nodes render
graph.resetCells(cells)
I am pretty new to angularjs and flot charts. I am trying to add click events to my stacked bar charts so that once I click a stack it displays the categories information but I am not sure if am doing it right.
Please help take a look
I already plot my chart in angularjs directive
see http://jsfiddle.net/6h1gL2sh/10/ here
App.directive('chart', function () {
return {
restrict: 'EA',
link: function (scope, elem, attrs) {
var chart = null,
options = {
series: {
stack: true,
bars: {
show: true,
clickable: true,
barWidth: 0.1,
align: "center"
}
},
axisLabels: {
show: true
},
xaxis: {
axisLabel: 'Products',
axisLabelUseCanvas: true,
axisLabelFontSizePixels: 12,
axisLabelPadding: 5,
mode: "categories",
tickLength: 0
},
yaxis: {
axisLabel: 'Pass/Fail Count',
axisLabelUseCanvas: true,
axisLabelFontSizePixels: 12,
axisLabelPadding: 5
},
grid: {
hoverable: true,
clickable: true
}
}
var data = scope[attrs.ngModel];
scope.$watch(attrs.ngModel, function (v) {
if (!chart) {
chart = $.plot(elem, v, options);
elem.show();
} else {
chart.setData(v);
chart.setupGrid();
chart.draw();
}
});
$(elem).bind("plotclick", function (event, pos, item) {
scope.$apply(function () {
if (item) {
scope.dis = item.series.xaxis.categories[item.dataIndex].label
}
});
});
}
};
});
Since you're trying to get an object's Key by value, you can't really access it as an array using bracket notation. I used a function that can be found on this SO question: JavaScript object get key by value
Then, I simply changed your click part to this:
elem.bind("plotclick", function (event, pos, item) {
if(item){
scope.dis= getKeyByValue(item.series.xaxis.categories, item.dataIndex);
scope.$apply();
}
});
Fiddle
I'm using KineticJS in conjunction with AngularJS and I want to be able to stash the necessary javascript into a directive. All of the examples I've seen for KineticJS wrap the required logic in a script tag using the defer attribute, i.e.
<script defer="defer">
window.onload = function() { ... }
</script>
Is it possible to load the template of the directive while deferring the execution of any business logic (in an equivalent way)? I've tried using the controller, link, compile functions to no avail. Here's an example:
'use strict';
angular.module('app')
.directive('canvasInitializer', ['$window', function ($window) {
return {
template: "<div id='canvas-container'></div>", // load this!
restrict: 'C',
compile: function (element, attrs) {
return {
post: function(scope, element, attrs) {
// defer this?
$window.onload = function () {
var stage = new Kinetic.Stage({
container: 'canvas-container',
width: 800,
height: 600
});
var layer = new Kinetic.Layer();
var blueRect = new Kinetic.Rect({
x: 50,
y: 75,
width: 100,
height: 50,
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 4
});
layer.add(blueRect);
stage.add(layer);
}
}
}
}
}
}]);
Aaaaaaand suddenly it looks like I found the answer to my problem. Wrapping the logic in $timeout(function () { ... }) did the trick. Notice that I didn't even provide a specific time for $timeout.
'use strict';
angular.module('app')
.directive('canvasInitializer', ['$timeout', function ($timeout) {
return {
template: "<div id='canvas-container'></div>"
restrict: 'C',
link: function (scope, element, attrs) {
$timeout(function () {
var stage = new Kinetic.Stage({
container: 'canvas-container',
width: 800,
height: 600
});
var layer = new Kinetic.Layer();
var blueRect = new Kinetic.Rect({
x: 50,
y: 75,
width: 100,
height: 50,
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 4
});
layer.add(blueRect);
stage.add(layer);
});
}
}
}]);