Angular – Highcharts Directive

Direktiven in Angular sind eine feine Sache, um HTML um neue Attribute zu erweitern. Hier zeigen wir eine Erweiterung für Highcharts.

In diesem Beispiel wollen wir unser HTML um das Attribut chart erweitern. Dort soll ein Chart per Highcharts angezeigt werden. Der Chart selbst ist ein Beispiel von der Highcharts-Seite. Die Daten sollen per Scope-Variable gesetzt werden und über einen Button sollen weitere Werte hinzugefügt werden können.

Zunächst benötigen wir einen Controller für unsere Angular-App.

var modul = angular.module('app', []);

modul.controller('dashboardController', function($scope) {
  ...
}

Die Angular-App nennen wir ‚app‘, den Controller ‚dashboardController‘. Beides können wir nun im HTML benutzen.

<body ng-app="app">
 <div ng-controller="dashboardController">
</div>
</body>

Als nächstes gehen wir die Direktive an.

modul.directive('chart', function () {
 return {
   restrict: 'C',
   replace: true,
   scope: {
     data: '=',
   },
   template: '<div id="container" style="margin: 0 auto"></div>',
   link: function (scope, element, attrs) {
     // hier erzeugen wir den chart
   }
 }
}

Hier definieren wir zunächst die Directive unter dem Namen ‚chart‘. Unter restrict legen wir fest, wonach das Matching erfolgen soll. In diesem Beispiel wollen wir nur nach der Klasse (C) matchen. Die scope-Variable data der Direktive soll von außen dann die Daten für den Chart erhalten.
Über die Funktion link können wir direkt den DOM manipulieren. Dort erzeugen wir den Chart.

link: function (scope, element, attrs) {
  var chart = new Highcharts.Chart({
    ...
  });
}

Hier im Beispiel verwenden wir das Highchart Basic-Line Demo, zu finden hier. Einzige Änderung ist, dass wir die vom Controller übergebenen Daten aus der Scope-Variable verwenden wollen.

</pre>
var chart = new Highcharts.Chart({
  ...
  series: [{
         name: 'Tokyo',
         data: scope.data
  }],
  ...
})

Nun können wir die Direktive im HTML verwenden.

<div class="chart" data="chartData"></div>

Die Scope-Variable chartData aus dem Controller übergeben wir als Attribut data an die Directive.

Jetzt fehlt noch der Button zum Hinzufügen neuer Daten.

<button ng-click="addValue()">Add Value</button>

Beim Klick soll die Funktion addValue() aufgerufen werden. Dort erzeugen wir beispielhaft einen Zufallswert und fügen diesem der Scope-Variable chartData hinzu.

$scope.addValue = function () {
   var value = Math.floor((Math.random() * 30) + 1);
   $scope.chartData.push(value);
 }

In der Directive bauen wir nun einen Watch auf die data – Variable ein. Wenn diese geändert wird, setzen wir die Daten der Chart-Series neu.

scope.$watch("data", function (newValue) {
  chart.series[0].setData(newValue, true);
}, true);

Und das war schon alles. Unser Chart sollte jetzt etwa so aussehen.

highchart-directive-1

Zur besseren Übersicht kommt hier noch mal der gesamte Code:

<!DOCTYPE html>
<html>
 <head>
 <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.min.js"></script>
 <script src="http://code.highcharts.com/highcharts.js"></script>
 <script src="http://code.highcharts.com/highcharts-more.js"></script>
 <link rel="stylesheet" href="style.css" />
 <script src="script.js"></script>
 </head>

 <body ng-app="app">
 <div ng-controller="dashboardController">
 <div class="chart" data="chartData"></div>
 <button ng-click="addValue()">Add Value</button>
 </div>
 </body>

</html></pre>

var modul = angular.module('app', []);

modul.controller('dashboardController', function($scope) {
 $scope.chartData = [7.0, 6.9, 9.5, 14.5, 18.2];

 $scope.addValue = function () {
   var value = Math.floor((Math.random() * 30) + 1);
   $scope.chartData.push(value);
 }
});

modul.directive('chart', function () {
 return {
   restrict: 'C',
   replace: true,
   scope: {
     data: '=',
   },
   controller: function ($scope, $element, $attrs) {

   },
   template: '<div id="container" style="margin: 0 auto"></div>',
   link: function (scope, element, attrs) {
     var chart = new Highcharts.Chart({
       chart: {
         renderTo: 'container',
         plotBackgroundColor: null,
         plotBorderWidth: null,
         plotShadow: false
       },
       title: {
         text: 'Monthly Average Temperature',
         x: -20 //center
       },
       subtitle: {
         text: 'Source: WorldClimate.com',
         x: -20
       },

       yAxis: {
         title: {
           text: 'Temperature (°C)'
         },
         plotLines: [{
           value: 0,
           width: 1,
           color: '#808080'
         }]
       },
       tooltip: {
         valueSuffix: '°C'
       },
       legend: {
         layout: 'vertical',
         align: 'right',
         verticalAlign: 'middle',
         borderWidth: 0
       },
       series: [{
         name: 'Tokyo',
         data: scope.data
       }]
    });
    scope.$watch("data", function (newValue) {
      chart.series[0].setData(newValue, true);
    }, true);

   }
 }
});

 

Falls Du es selbst live ausprobieren willst, ist hier der Link zu Plnkr: http://plnkr.co/edit/pM82a73B16dEcbGunkcm
Und natürlich hoffe ich wie immer, diese erstbeste Lösung war hilfreich.

Ähnliche Beiträge

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert