Skip to content

Instantly share code, notes, and snippets.

@pjsvis
Last active November 13, 2020 00:56
Show Gist options
  • Star 21 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save pjsvis/6210002 to your computer and use it in GitHub Desktop.
Save pjsvis/6210002 to your computer and use it in GitHub Desktop.
Angular directive for jQuery sparkline
// Requires jQuery from http://jquery.com/
// and jQuerySparklines from http://omnipotent.net/jquery.sparkline
// AngularJS directives for jquery sparkline
angular.module('sparkline', []);
angular.module('sparkline')
.directive('jqSparkline', [function () {
'use strict';
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, elem, attrs, ngModel) {
var opts={};
//TODO: Use $eval to get the object
opts.type = attrs.type || 'line';
scope.$watch(attrs.ngModel, function () {
render();
});
scope.$watch(attrs.opts, function(){
render();
}
);
var render = function () {
var model;
if(attrs.opts) angular.extend(opts, angular.fromJson(attrs.opts));
console.log(opts);
// Trim trailing comma if we are a string
angular.isString(ngModel.$viewValue) ? model = ngModel.$viewValue.replace(/(^,)|(,$)/g, "") : model = ngModel.$viewValue;
var data;
// Make sure we have an array of numbers
angular.isArray(model) ? data = model : data = model.split(',');
$(elem).sparkline(data, opts);
};
}
}
}]);
@itrond
Copy link

itrond commented Nov 29, 2013

Thank you Peter! :-) works very nice:
remember to use {{ around you opts, like:
.... jq-sparkline ng-model="yourData" opts="{{ {type:'line', width:'200px', height:'45px'} }}" ....

@wimvanleuven
Copy link

Hmmm ... can't seem to get it work. I notice the module/directive to get loaded, but the rendering never gets triggered.

In my HTML code, I've set this up as a

Any ideas? Thanks already!
-wim

@Ercenk
Copy link

Ercenk commented Apr 7, 2014

wim, try setting the objectEquality flag of $watch for the ngModel to true, if your ngModel is an array, and you are changing it programmatically.

e.g. if you are adding elements to the model array pointed to by the ng-model attribute, change the code to:

scope.$watch(attrs.ngModel, function () {
render();
}, true);

@DaveCollinsJr
Copy link

I don't suppose anyone has a JSFiddle of this working, do they?

@DaveCollinsJr
Copy link

If it helps anyone who uses coffeescript... Here is a version of the above that is working for me in a project:

  .directive "mySpark", ->
    restrict: "A"
    require: "ngModel"
    link: (scope, elem, attrs, ngModel) ->
      opts = {}

      opts.type = attrs.type || 'bar'
      opts.barColor = attrs.barColor || '#ffffff'
      opts.height = attrs.height || '35px'
      opts.barWidth = attrs.barWidth || '5px'
      opts.barSpacing = attrs.barSpacing || '2px'
      opts.zeroAxis = attrs.zeroAxis || 'false'

      scope.$watch attrs.ngModel, ((value) ->
        render()
      ), true

      scope.$watch attrs.opts, ((value) ->
        render()
      ), true

      render = () ->
        angular.extend opts, angular.fromJson(attrs.opts) if attrs.opts

        model = ngModel.$viewValue

        if angular.isArray(model)
          data = model
        else
          if model?
            data = model.split(",")
          else
            data = []

        $(elem).sparkline data, opts

Using it:

<div my-spark ng-model="daily_meter_uptime.scaled_historical_values"/>

used a deep watch on the values and it is working great. Thanks for taking the time to write this up!!

@nozelrosario
Copy link

Thanks !! works like charm :)

@anilsingh581
Copy link

@christheyounger
Copy link

Wrapping the jquery bit in $timeout() helped me.

@dylannnn
Copy link

This is great! But how can I use this directive to create a Composite inline graph? For example two line in one graph. I tried many way but failed. Thanks

Sample image:
download 1

@adanylov
Copy link

adanylov commented Jun 7, 2016

In case of composite sparkline:

function compositeSparkline(): ng.IDirective {

    function link(scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes) {
        var getOptions = () => {
            var options = {
                chart1: angular.extend({ type: 'line', data: [] }, scope.$eval(attrs['chart1'])),
                chart2: angular.extend({ type: 'line', data: [] }, scope.$eval(attrs['chart2']))
            }

            return options;
        };

        var render = () => {
            var opts = getOptions();

            // draw chart1
            (<any>jQuery(element)).sparkline(opts.chart1.data, opts.chart1);

            // draw chart2
            (<any>jQuery(element)).sparkline(opts.chart2.data, opts.chart2);
        };

        // Watch for changes to the directives options
        scope.$watch(getOptions, render, true);

        render();
    }

    return {
        restrict: 'A',
        scope: {},
        link: link
    };
}

angular.module('sparkline').directive('ngCompositeSparkline', compositeSparkline);

It is less flexible because you need to pass arrays of integer for chart1 and chart2 options into the directive... But it is just a starting point for the extensions

@roelzkie15
Copy link

May i know where can i find the implementation code? Its a big help.

@Hnasante
Copy link

+1

May I know how to make this work for angular 4, thanks in advance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment