Verschachtelte Ansichten mit AngularJS
AngularJS unterstĂŒtzt von Haus aus weder zusammengesetzte noch verschachtelte Ansichten, was sich aber mit Hilfe des Projekts UI-Router nachrĂŒsten lĂ€sst. Es stellt die Dienste $stateProvider und $urlRouterProvider zur VerfĂŒgung und ermöglicht eine flexible Konfiguration von ZustĂ€nden und Adressen.
Wer Webanwendungen auf Basis eines Frameworks wie beispielsweise AngularJS [1] entwickelt, benötigt in der Regel UnterstĂŒtzung fĂŒr verschachtelte und zusammengesetzte Ansichten.
Zu diesem Zweck enthĂ€lt AngularJS die ngView [2]-Direktive, deren Nutzen allerdings begrenzt ist: Zwar erlaubt sie es dem Entwickler, eine Ansicht in eine andere zu integrieren, unterstĂŒtzt dies jedoch nicht verschachtelt. Auch ist es nicht möglich, in einer Ansicht mehrere ngView-Direktiven gleichzeitig zu integrieren.
UI-Router als Ausweg
Einen Ausweg bietet die zusÀtzliche Komponente UI-Router [3], die im Rahmen des AngularUI [4]-Projekts entwickelt wird.
Um diese Komponente verwenden zu können, muss man zunÀchst die entsprechende JavaScript-Datei herunterladen und in die Webanwendung einbetten - nach AngularJS, wohlgemerkt:
<script type="text/javascript" src="angular.js"></script>
<script type="text/javascript" src="angular-ui-states.js"></script>
Innerhalb der Webanwendung kann man den UI-Router dann mit Hilfe des SchlĂŒssels ui.compat als AbhĂ€ngigkeit laden:
var app = angular.module('app', [ 'ui.compat' ]);
Danach kann man die beiden neuen Dienste $urlRouterProvider und $stateProvider verwenden, um die einzelnen ZustÀnde der Webanwendung zu konfigurieren.
Ansichten konfigurieren
In der einfachsten Variante konfiguriert man einen Zustand und weist diesem eine Adresse, eine Ansicht und gegebenenfalls einen Controller zu:
app.config([ '$stateProvider', function ($stateProvider) {
'use strict';
$stateProvider
.state('dashboard', {
url: '/',
templateUrl: '/dashboard/dashboardLayout.html',
controller: '/dashboard/dashboardController.js'
});
}]);
Benötigt man mehrere derartige ZustĂ€nde, kann man die Funktion state verkettet aufrufen und auf die gleiche Art beliebige weitere ZustĂ€nde definieren. Wichtig ist, dass man an Stelle der ngView-Direktive nun die uiView-Direktive verwendet, die der UI-Router zur VerfĂŒgung stellt.
Innerhalb einer Ansicht kann man auch mehrere uiView-Direktiven verwenden, muss diesen dann allerdings einen eindeutigen Bezeichner zuweisen:
<div ui-view="mailView"></div>
<div ui-view="calendarView"></div>
ZusÀtzlich muss man innerhalb der Konfiguration festlegen, welche Ansicht welche Webseite anzeigen soll. Dazu ersetzt man die Eigenschaften templateUrl und controller durch die Eigenschaft views und weist dieser ein Konfigurationsobjekt zu, das die einzelnen Zuordnungen vornimmt:
.state('dashboard', {
url: '/',
views: {
'': {
templateUrl: '/dashboard/dashboardLayout.html',
controller: '/dashboard/dashboardController.js'
},
'mailView@dashboard': {
templateUrl: '/mails/unansweredMailsView.html',
controller: '/mails/unansweredMailsController.js'
},
'calendarView@dashboard:' {
templateUrl: '/calendar/todaysTasksView.html',
controller: '/calendar/todaysTasksController.js'
}
}
});
Die namenlose Ansicht stellt dabei die Elternansicht dar, in der die beiden untergeordneten Ansichten dargestellt werden.
Ansichten verschachteln
Von Zeit zu Zeit kann es gewĂŒnscht sein, fĂŒr verschiedene, jedoch logisch zusammenhĂ€ngende Ansichten ein gemeinsames Layout zu definieren. So kann es beispielsweise sinnvoll sein, die Struktur aller E-Mail-Ordner ordnerĂŒbergreifend anzuzeigen, aber jeden einzelnen Ordner direkt ĂŒber eine individuelle Adresse auswĂ€hlen zu können.
Dazu muss man zunĂ€chst den Zustand mails definieren, der das grundlegende Layout fĂŒr die verschiedenen Ordner enthĂ€lt. Dies erfolgt auf dem bereits bekannten Weg, weist dem Layout aber keine eigene Adresse zu, da es nicht sinnvoll ist, die Ansicht ohne konkreten Ordner auszuwĂ€hlen:
.state('dashboard', {
// ...
})
.state('mails', {
templateUrl: '/mails/mailsLayout.html',
controller: '/mails/mailsController.js'
});
Um darĂŒber hinaus auch zu verhindern, dass dieser Zustand per Code aufgerufen werden kann, kann man zusĂ€tzlich die Eigenschaft abstract definieren und ihr den Wert true zuweisen:
.state('mails', {
abstract: true,
templateUrl: '/mails/mailsLayout.html',
controller: '/mails/mailsController.js'
});
Danach kann man die untergeordneten ZustĂ€nde definieren, denen man dann wiederum eine Adresse zuweist. Damit AngularJS die Hierarchie zwischen den ZustĂ€nden erkennt, muss man darĂŒber hinaus die Bezeichnungen der untergeordneten ZustĂ€nde mit dem Namen des ĂŒbergeordneten als PrĂ€fix versehen:
.state('mails', {
// ...
})
.state('mails.inbox', {
url: '/mails/inbox',
templateUrl: '/mails/inboxView.html',
controller: '/mails/inboxController.js'
});
Ruft man anschlieĂend im Webbrowser die Adresse /mails/inbox auf, lĂ€dt AngularJS zunĂ€chst die ĂŒbergeordnete Ansicht und bettet die untergeordnete Ansicht danach an der Position der entsprechenden uiView-Direktive ein.
Weiterleitungen definieren
Zu guter Letzt ist nun noch wĂŒnschenswert, dass ein Aufruf der bislang nicht zugeordneten Adresse /mails auf die Adresse /mails/inbox weitergeleitet wird. Dies kann man nicht ĂŒber den $stateProvider definieren, stattdessen muss man hierfĂŒr auf den $urlRouterProvider zurĂŒckgreifen:
app.config([ '$stateProvider', '$urlRouterProvider',
function ($stateProvider, $urlRouterProvider)
{
'use strict';
$stateProvider
// ...
$urlRouterProvider
.when('/mails', '/mails/inbox');
}]);
DarĂŒber hinaus kann man an dieser Stelle auch eine Standardadresse definieren, auf die AngularJS dann weiterleitet, wenn der Anwender eine nicht zugewiesene Adresse aufruft:
$urlRouterProvider
.when('/mails', '/mails/inbox')
.otherwise('/');
tl;dr: AngularJS unterstĂŒtzt von Haus aus weder zusammengesetzte noch verschachtelte Ansichten, das kann man aber mit Hilfe des Projekts UI-Router nachrĂŒsten. Es stellt die beiden neuen Dienste $stateProvider und $urlRouterProvider zur VerfĂŒgung und ermöglicht eine flexible Konfiguration von ZustĂ€nden und Adressen. ( [5])
URL dieses Artikels:
https://www.heise.de/-1857240
Links in diesem Artikel:
[1] http://angularjs.org/
[2] http://docs.angularjs.org/api/ng.directive%3AngView
[3] https://github.com/angular-ui/ui-router
[4] https://github.com/angular-ui
[5] mailto:webmaster@goloroden.de
Copyright © 2013 Heise Medien