Highcharts mit .NET erstellen und mit AngularJS “wrapper” darstellen


Wer seine Daten mit Charts visualisieren muss hat im Web eine große Auswahl an Anbietern die Chartbibliotheken zur Verfügung stellen. Ich habe dafür bisher immer Google Charts oder Highcharts verwendet. Leider habe ich bisher noch keine alternative Chartbibliothek für AngularJS gefunden, die genauso umfangreich ist wie z.B. Highcharts.

Das schöne an Highcharts, ist das sich die benötigte Datenstruktur sehr einfach mit Hilfe von .NET Klassen abbilden lässt. Wenn man sich die Dokumentation einmal näher anschaut erkennt man schnell das man viele Charts sehr gut mit ein paar .NET Klassen darstellen kann. Diese werden dann beim AJAX Call in JSON konvertiert und können einfach dem Highchart als Datenquelle übergeben werden.

Dies kann z.B. folgendermaßen aussehen:

image

Es muss nur darauf geachtet werden, das die Property Namen kleingeschrieben werden, bzw. genauso geschrieben werden wie in der Dokumentation von Highcharts angegeben.

public class BasicHighChart
{
   public BasicHighChart()
    {
        title = new Title();
        subtitle = new Title();
        chart = new Chart();
        legend = new Legend();
    }

    public Title title { get; set; }

    public Title subtitle { get; set; }

    public Chart chart { get; set; }

    public Legend legend { get; set; }

    public dynamic xAxis { get; set; }

    public dynamic yAxis { get; set; }

    public dynamic series { get; set; }
}

public class Chart
{
    public Chart()
    {
        type = "bar";
        zoomType = string.Empty;
    }

    public string type { get; set; }

    public string zoomType { get; set; }
}

public class Legend
{
    public Legend()
    {
        enabled = true;
        borderWidth = 0;
        layout = "vertical";
        align = "right";
        verticalAlign = "middle";
    }

    public bool enabled { get; set; }

    public string layout { get; set; }

    public string align { get; set; }

    public string verticalAlign { get; set; }

    public int borderWidth { get; set; }
}

...

Das ganze lässt sich grenzenlos ausbauen – je nach dem welche Bedürfnisse man hier abdecken muss.

Die Daten können dann z.B. über den Controller und ein JsonResult zur Verfügung gestellt werden.

 public JsonResult LoadTempratureChartData()
 {
     BasicHighChart chart = new BasicHighChart();
     chart.chart.type = "line";
     chart.chart.zoomType = "x";
     chart.title.text = ".NET Generierte Daten";
     chart.subtitle.text = "chart subtitle";
     chart.legend.enabled = true;
     chart.xAxis = new { categories = new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" } };
     chart.yAxis = new { title = new Title() { text = "Temperature (°C)" } };

     var series = new List();
     series.Add(new BasicSeries() { name = "Dresden", data = new List() { 7.0, 4.3, 8.5, 7.7, 19.9, 22.4, 26.1, 31.0, 16.6, 15.2, 6.2, 4.3 } });
     series.Add(new BasicSeries() { name = "Hamburg", data = new List() { 2.2, 7.2, 5.2, 8.3, 18.2, 24.4, 28.9, 32.6, 19.5, 13.8, 3.1, 5.3 } });
     series.Add(new BasicSeries() { name = "Berlin", data = new List() { 5.0, 6.0, 2.8, 9.2, 16.9, 23.5, 29.1, 36.1, 15.2, 12.2, 5.7, 2.6 } });
     chart.series = series;

     return Json(chart, JsonRequestBehavior.AllowGet);
 }

 public JsonResult LoadIllnessChartData()
 {
     BasicHighChart chart = new BasicHighChart();
     chart.chart.type = "line";
     chart.chart.zoomType = "x";
     chart.title.text = ".NET Generierte Daten";
     chart.subtitle.text = "chart subtitle";
     chart.legend.enabled = true;
     chart.xAxis = new { title= new Title() { text = "Krankheitstage"} };
     chart.yAxis = new { title = new Title() { text = "Alter" } };

     var series = new List();
     series.Add(new PointSeries() { name = "Bert", data = new List() { new object[] { 23, 2 }, new object[] { 24, 5 }, new object[] { 25, 8 }, new object[] { 26, 5 }, new object[] { 27, 1 } } });
     series.Add(new PointSeries() { name = "Hugo", data = new List() { new object[] { 23, 8 }, new object[] { 24, 5 }, new object[] { 25, 3 }, new object[] { 26, 4 }, new object[] { 27, 2 } } });
     series.Add(new PointSeries() { name = "Gert", data = new List() { new object[] { 23, 1 }, new object[] { 24, 1 }, new object[] { 25, 2 }, new object[] { 26, 5 }, new object[] { 27, 7 }, new object[] { 28, 2 } } });
     chart.series = series;

     return Json(chart, JsonRequestBehavior.AllowGet);
 }

Damit die Daten auch in AngularJS verwendet werden können empfehle ich für den Anfang eine einfache Direktive, an die z.B. einfach nur die JSON Daten übergeben werden.

app.directive("sqChart", function () {
    return {
        restrict: 'A',
        replace: true,
        scope: {
            chartData: "="
        },
        link: function (scope, element, attr) {
            scope.$watch('chartData.series', function () {
                if (scope.chartData !== undefined && scope.chartData.series !== undefined) {
                    element.highcharts(scope.chartData);
                }
            },true);
        }
    }
});

Die Direktive nimmt über das Attribut “chart-data” die Daten entgegen die dargestellt werden sollen und erstellt ein neues Highcharts Element mit diesen übergebenen Daten. Da wir die Daten nicht gleich beim Aufbau der Seite zur Verfügung haben, sondern diese über AJAX nachladen, wird der watcher in der Direktive benötigt. Damit ist es z.B. auch möglich die Anzeigedaten zu aktualisieren und das Diagramm zeichnet sich automatisch neu.

 <div sq-chart chart-data="ctrl.ViewModel.Temperature"></div>

Die restliche Anwendung besteht dann nur noch daraus die App und den Controller zu definieren und die Daten abzurufen:

var app = angular.module("main.app", []);
app.controller("mainCtrl", function ($http) {
    var that = this;
    this.ViewModel = {};

    $http.get('/Home/LoadTempratureChartData').then(function (result) {
        that.ViewModel.Temperature = result.data;
    });

    $http.get('/Home/LoadIllnessChartData').then(function (result) {
        that.ViewModel.Illness = result.data;
    });
  
});

Mehr ist für das simple Darstellen eines Highcharts Diagramms mit AngularJS nicht notwendig. Hier gibt es bestimmt noch andere alternative Lösungen über Vorschläge freue ich mich immer gern.

Das Beispiel kann wie immer auch bei Codeplex heruntergeladen bzw. der komplette Code eingesehen werden.

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s