Gitter und Winkel

Das Grid von Kendo UI mit AngularJS nutzen
Kommentare

Die populäre Komponentenbibliothek Kendo UI aus dem Hause Telerik bietet ein äußerst flexibles Grid für HTML-basierte Anwendungen. Mithilfe von bereitgestellten Direktiven lässt es sich komfortabel in AngularJS-Projekte einbinden.

Kaum eine Geschäftsanwendung kommt ohne ein Grid zur Präsentation tabellarischer Daten aus. Aufgrund der damit einhergehenden Komplexität stützen sich die meisten Teams auf Grid-Implementierungen von Drittanbietern. Eine solche findet sich in der Komponentenbibliothek Kendo UI. Sie bietet eine Vielzahl an Möglichkeiten, wie Sortieren, Gruppieren und verschiedene Ansätze zum Editieren von Einträgen. Dieser Artikel zeigt, wie Grid in AngularJS-Projekten genutzt werden kann. Detaillierte Beschreibungen zur gesamten Bibliothek sind im Demokatalog direkt auf der Seite des Herstellers zu finden.

Beispielprojekt

Das hier präsentierte Beispiel zur Demonstration des Grids zeigt eine Flugverwaltung. Sie stellt Flüge in einer Tabelle dar, die sich direkt aus dieser heraus verändern bzw. ergänzen lassen (Abb. 1, Abb. 2 und Abb. 3). Der Benutzer kann die geladenen Flüge sortieren, gruppieren und filtern.

Abb.1: Ansicht des fertigen Kendo-Beispiels

Abb.1: Ansicht des fertigen Kendo-Beispiels

Abb.2: Gruppieren nach Abflugort

Abb.2: Gruppieren nach Abflugort

Abb.3: Filtern nach Abflugort

Abb.3: Filtern nach Abflugort

In Listing 1 ist die modellierte Flugentität FlightEntity in Form eines einfachen JavaScript-Objekts dargestellt.

Listing 1
var FlightEntity = function(name, departure, destination, startTime, endTime, passengersCount) {
  var self = this; 

  //Auto-generated self._id; 
  self.name = name; 
  self.departure = departure; 
  self.destination = destination; 
  self.startTime = startTime; 
  self.endTime = endTime; 
  self.passengersCount = passengersCount; 
};

Einbindung von Kendo-Komponenten mittels Direktiven

Im Rahmen der Entwicklung der Komponente ist eigens für AngularJS ein Satz von Direktiven entwickelt worden, um den deklarativen Entwicklungsansatz von AngularJS zu unterstützen. Für die Nutzung ist die Kendo Library (kendo.all.min.js) sowie das Direktivenpaket (angular-kendo.js) in der Datei index.htm zu laden (Listing 2). Optional dazu lässt sich ein Sprachpaket (in diesem Fall für Deutsch) vom GitHub-Projekt Kendo Global einbinden. Wichtig ist zu beachten, dass die Einbindung nach dem Referenzieren der angular.js-Datei zu erfolgen hat, da es sonst zu Abhängigkeitsfehlern kommen kann.

 [...]
<script src="PFAD_ZU/jquery/jquery.min.js"></script>
<script src="PFAD_ZU/angular/angular.js"></script>
<script src="PFAD_ZU/kendo/kendo.all.min.js"></script>
<script src="PFAD_ZU/kendo/kendo.de-DE.js"></script>
<script src="PFAD_ZU/kendo/angular-kendo.js"></script>

Des Weiteren ist es nötig, der AngularJS-Anwendung mitzuteilen, dass künftig die Kendo-Direktiven zu verwenden sind. Das geschieht durch den Verweis auf das Modul kendo.directives als Abhängigkeit, wie in Listing 2 gezeigt.

Listing 2
angular
  .module('demoApp', [
    'ngAnimate', 
    'ngCookies', 
    'ngResource', 
    'ngRoute', 
    'ngSanitize', 
    'ngTouch', 
    'kendo.directives'
  ]) 
  .config(function ($routeProvider) {
  // Konfiguration des routeProviders ... 
  });

Im Gegensatz zum deklarativen Ansatz, also der Anreicherung der Anzeigeebene mit Komponenten (Listing 4) steht der imperative Ansatz aus Listing 3. Dieser sieht vor, dass die Implementierung des Gitters im Code beispielsweise mit jQuery vorzunehmen ist.

<div id="grid"></div>

<script>
  $(document).ready(function () {
    $("#grid").kendoGrid({
      dataSource: {
        ... 
      },
      ... 
    });
  });
</script>

Über Vor- und Nachteile der jeweiligen Methode lassen sich ganze Glaubenskriege führen, entscheidend ist in diesem Fall, dass sich AngularJS klar für die deklarative Methode entscheidet und die View des Beispiels im Sinne von Best Practices auch dementsprechend erstellt ist. Angular Kendo stellt dafür ein Set an Direktiven zur Verfügung, die sich durch folgende Punkte auszeichnen:

  • Die verwendete Komponente ist durch einen Bindestrich gekennzeichnet, z. B. kendo-grid.
  • Jedes Konfigurationsattribut ist durch ein führendes k- deklariert.
  • Die Komponente kann direkt an ein Objekt im jeweiligen Scope gebunden werden, ohne die Notwendigkeit, es zuvor in einer Kendo Observable zu verpacken.

Bezüglich des zweiten Punkts ist in Listing 4 zu sehen, dass sich das Attribut granular definieren lässt. Neben den hier verwendeten Attributen data-source und options, gibt es noch weitere wie k-ng-delay für die verzögerte Bindung des Gitters und k-on-change, um auf Events des Grids zu binden oder k-column, um die Spaltendefinition direkt im Markup vorzunehmen. Letzteres wird jedoch rasch unübersichtlich und sollte möglichst vermieden werden. Stattdessen kann dies direkt im jeweiligen Controller erfolgen. Um das Testen des Codes zu vereinfachen, empfiehlt es sich, die Definition wie später gezeigt in eine eigene Factory auszugliedern.

Listing 4
<div ng-controller="KendoGridCtrl">
  <h3>Flüge vom {{flightDate | date: 'dd.MM.yyyy'}}</h3>
  <div kendo-grid
    k-data-source="kendoGridVM.dataSource"
    k-options="kendoGridVM.gridOptions"></div>
</div>

Die jeweiligen Eigenschaften werden vom KendoGridCtrl aus Listing 5 bereitgestellt. Wie schon zuvor erwähnt, ist die Definition des Grid Bindings in eine separate Factory ausgegliedert, die der Controller als Abhängigkeit namens kendoGridDataSource lädt. Das Ergebnis ist dem View-Model $scope.kendoGridVM zugeordnet.

Listing 5
angular.module('demoApp') 
  .controller('KendoGridCtrl', function ($scope, kendoGridDataSource) {

    $scope.flightDate = new Date();
    $scope.kendoGridVM = kendoGridDataSource; 

  });

Die Factory kendoGridDataSource, die Listing 6 zeigt, dient nun als gekapselte Auslagerung der Grid-Konfiguration. Zu Beginn legt das Beispiel den REST-Endpunkt des Backend-Projekts in der Variablen serviceURL ab. Diese wird im dataSource-Attribut für das Ansprechen der jeweiligen Funktion benötigt. DataSource ist ein Objekt des Typs kendo.data.DataSource, das Einstellungen zur Datenherkunft ermöglicht. Durch die Eigenschaft type ist die Übertragungsart auf JSON gesetzt. Die DataSource stellt zudem die wichtige Option transport zur Verfügung, mit deren Hilfe der Entwickler bestimmt, wie der Zugriff der jeweiligen Grid-Features ablaufen soll.

Jedes Kommando besteht aus einem anzusprechenden Endpunkt. Die Eigenschaft async bewirkt des Weiteren, dass Daten nicht parallel zum Aufbau des Grids zu laden sind, sondern erst nach dem vollständigen Erhalt der Daten.

Listing 6
/*global kendo*/
'use strict'; 

angular.module('demoApp') 
       .factory('kendoGridDataSource', 
  function ()
  {
    // Der Endpunkt unseres REST-Services
    var serviceURL = 'http://localhost:8080/kendogrid'; 

    return {
      // Deklaration des Datenzugriffs
      dataSource: new kendo.data.DataSource({
        // NodeJS + Restify übertragen JSON
        type: 'json', 
        // Beschreibung der Datenübertragung
        transport: {
          // Lesen von Flügen
          // GET: /kendogrid
          read: {
            // Grid erst nach geladenen Daten aufbauen
            async: false, 
            // Standard REST -> GET ohne Parameter
            url: serviceURL, 
            dataType: 'json'
          },
          // Update eines Flugs
          // PUT: /kendogrid
          update: {
            // URL auch als Funktion definierbar
            url: function (data) 
            {
              return serviceURL + '/' + data._id; 
            },
            // erzwinge PUT für Updates
            type: 'PUT', 
            dataType: 'json'
          },
          // Löschen eines Flugs
          // DELETE: /kendogrid/:id
          destroy: {
            url: function (data) 
            {
                return serviceURL + '/' + data._id; 
              },
            type: 'delete', 
            dataType: 'json'
          },
          // Anlegen eines neuen Flugs
          // POST: /kendogrid
          create: {
            url: serviceURL, 
            type: 'post', 
            dataType: 'json'
          }
        },

Eine weitere Option der dataSource-Eigenschaft, im zweiten Teil der Grid-Konfiguration in Listing 7, ist batch, das die Versendung der Daten in einzelnen Anforderungen oder als gebündeltes Array von einzelnen Änderungen durchführt. Das kann zur Schonung der Bandbreite beitragen, ist jedoch dementsprechend gesondert im Backend zu behandeln. Ebenfalls bietet das Kendo UI Grid die Option, die Seitennavigation, -sortierung und -filterung entweder durch den Server durchführen zu lassen oder dies selbst am Frontend vorzunehmen. Das Beispiel verwendet hierbei explizit die frontendseitigen Features, was bei kleinen Datenmengen durchaus akzeptabel ist und nachfolgende Serveranfragen unterdrückt. Bei größeren Datenmengen hingegen kann sich das negativ auf die Performance der Anwendung auswirken, im Besonderen in Anbetracht der Leistung von mobilen Endgeräten.

Stellen Sie Ihre Fragen zu diesen oder anderen Themen unseren entwickler.de-Lesern oder beantworten Sie Fragen der anderen Leser.

Den wichtigsten Teil der Konfiguration stellt das schema dar, das beschreibt, wie die übermittelten Entitäten des Backends zu behandeln sind. Hierbei handelt es sich um die zuvor in Listing 1 beschriebene Flugentität. Die Eigenschaft id deklariert, welche Entitätseigenschaft als eindeutiger Schlüssel zu verwenden ist. Die Auflistung fields dient dazu, jede weitere Entitätseigenschaft auf Felder abzubilden und in diesem Zuge etwaige Validierungen oder Typisierungen vorzunehmen.

Im Beispiel sind alle Felder als Pflichtfelder zu behandeln, um im Fehlerfall eine automatische Anzeige des Grids zu provozieren. Des Weiteren ist die Eigenschaft _id als nicht veränderbar definiert und passengersCount als Nummer typisiert, die zumindest fünf Gäste voraussetzt.

Listing 7
batch: false,
// Clientseitige Features aktivieren
serverPaging: false,
serverSorting: false,
serverFiltering: false,
pageSize: 10,
// Model Beschreibung
schema: {
  model: {
    // Primärer Identifikator eines Flugs
    id: '_id',
    fields: {
      // ID kann nicht verändert werden
      _id: { editable: false, nullable: true},
      name: { validation: { required: true } },
      departure: { validation: { required: true } },
      destination: { validation: { required: true } },
      startTime: { validation: { required: true } },
      endTime: { validation: { required: true } },
      passengersCount: { type: 'number', validation:
        { min: 5, required: true }
      }
    }
}
}
}),

In der Eigenschaft gridOptions der Factory sind die jeweiligen clientseitigen Features aktiviert, im Besonderen das Inlineeditieren. Dabei handelt es sich um die Möglichkeit zum direkten Verändern der Einträge innerhalb des Grids (Abb. 4). Listing 8 zeigt den Abschluss der Grid-Konfiguration. Eine toolbar ist für das Erstellen eines neuen Flugs in Verwendung. Dieses Array erhält pro Schaltfläche ein Objekt. Durch das Setzen des entsprechenden Namens lässt sich wie im Beispiel gezeigt eine Schaltfläche zum Hinzufügen neuer Flüge darstellen. Die Eigenschaft text gibt den anzuzeigenden Textinhalt der Schaltfläche an.

Abb. 4: Kendo Grid im aktiven Inlineeditiermodus

Abb. 4: Kendo Grid im aktiven Inlineeditiermodus

Zu guter Letzt definiert die columns-Eigenschaft, wie die jeweiligen Spalten im Gitter darzustellen sind. Das Kendo-API stellt hierfür zahlreiche weitere Funktionen wie Aggregate und Einstellungen, etwa ob die jeweilige Spalte sortiert, gefiltert oder gruppiert werden darf, zur Verfügung. Diese und weitere sind der API-Dokumentation zu entnehmen.

Listing 8
gridOptions: {
      // Features aktivieren
      sortable: true,
      selectable: true,
      groupable: true,
      filterable: {
        mode: 'row'
      },
      // Änderungen direkt im Grid vornehmen
      editable: 'inline',
      // Hinzufügen Button über Grid
      toolbar: [
        { name: 'create', text: 'Neuen Flug anlegen' }
      ],
      // Definition der Sichtbaren spalten Definition der sichtbaren Spalten
      columns: [
        // Entity property + Spaltenname
        { field: 'name', title: 'Flugname' },
        { field: 'departure', title: 'Abflugort' },
        { field: 'destination', title: 'Ankunftsort' },
        { field: 'startTime', title: 'Abflugszeit' },
        { field: 'endTime', title: 'Ankunftszeit' },
        { field: 'passengersCount', title: 'Passagiere #' },
        // CRUD Operationen pro Zeile
        {
          command: [
            { name: 'edit', text: 'Editieren' },
            { name: 'destroy', text: 'Löschen' }
          ],
          title: ' ',
          width: 220
        }
      ]
    }
  };
});

Das Grid in Kendo UI bietet eine Fülle an Möglichkeiten zur Präsentation von tabellarischen Daten in HTML-Anwendungen. Es bietet Umfangreiche Optionen zum Filtern, Sortieren, Gruppieren und Editieren von Einträgen. Die von Telerik zur Verfügung gestellten Direktiven vereinfachen auch die Nutzung in AngularJS-Projekten. Wer sich einen Überblick über die Möglichkeiten von Kendo UI im Allgemeinen oder des Grids im Speziellen machen möchte, findet eine Beispielsammlung auf den Seiten des Herstellers.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -