Very Basic Angular App: Teil 1

Meine eigene Homepage diente mir als Testprojekt für die erste AngularJS App. Ziel war eine möglichst einfache, nachvollziehbare Struktur der Applikation, wenige Seiten, die nachgeladen werden sowie eine sortier- und filterbare Ansicht meiner Referenzprojekte.

Im ersten Teil beschreibe ich den Rahmen der App, das Aufteilen der HTML Dateien, das Anzeigen der Inhalte und gebe einen Hinweis zur google Indexierung / SEO. Im zweiten Teil wird die Darstellung der Projektliste erklärt, einschließlich der Sortier- und Filtermöglichkeiten.

Ich kann und möchte mich nicht in die allgemeine Diskussion einmischen, ob und wie AngularJS ein mehr oder weniger geeignetes Framework für diesen oder jenen Zweck ist. Noch möchte ich mich zur Performance äußern oder dazu, ob das Framework für Enterprise IT geschaffen wurde und für kleine WebApps vollkommen ungeeignet ist. Diese Diskussion ist in vollem Gange – stellvertretend hier zwei Beiträge:
The problem with Angular
An Overview of AngularJS for Managers

Hier also ein sehr einfaches Beispiel einer Site mit 3 Unterseiten: Die Links des Menüs verursachen kein Neuladen der gesamten Website, sondern werden mehr oder weniger sanft eingeblendet. Die Inhalte der einzelnen Seiten liegen im HTML Format vor und werden in einem Verzeichnis namens „partials“ gespeichert.

<div id="work" class="clearfix">
  <div id="overview" class="sixteen columns">
    <h3>Webentwicklung, Webdesign, Internet Beratung<br>TYPO3 Integrator.</h3>
    <hr />
  </div>
  <div class="eight columns">
    <h4>Leistungen</h4>
    <ul class="disc">
      <li>Webdesign und Konzeption</li>
      <li>Internet Beratung</li>
      <li>CMS TYPO3</li>
      ...
    </ul>
  </div>
  ...
</div>

Diese Datei heißt work.html

In einem Verzeichnis namens „templates“ liegen die HTML Dateien, die den Rahmen für die Inhalte zur Verfügung stellen, in meinem Beispiel header.html und footer.html.

In der Datei header.html steht dann u.a. folgendes:

<nav>
  <ul>
    <li><a href="#/">Arbeit</a></li> 
    <li><a href="#/about">Über mich</a></li>
    <li><a href="#/referenzen">Referenzen</a></li>
  </ul>
</nav>

Soweit eigentlich kaum etwas Besonderes. Das kommt erst in der index.html:

<body ng-app="myApp">
  <div ng-include='"templates/header.html"'></div>  
  <div ng-view class="fade-animate"></div>
  <div ng-include='"templates/footer.html"'></div>      
 
  <script src="http://code.angularjs.org/1.2.28/angular.min.js"></script>
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular-route.min.js"></script>
  <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular-animate.min.js"></script>
  <script src="js/app.js"></script>
</body>

Hier fallen die Attribute ng-app im Body-Tag sowie ng-include und ng-view auf. Ersteres initialisiert die Angular App (und bekommt als Wert den Namen der App, wie er vergeben wird – s.u.), letztere dienen zur Darstellung der Inhalte. Mit ng-include werden die bereits erwähnten Dateien header.html und footer.html geladen, der div mit ng-view zeigt den jeweiligen Inhalt an.

Ferner wird in der index.html das benötigte JavaScript geladen. Neben den Angular Dateien ist das die eigentliche Programmierung in der Datei app.js

Hier ist zunächst folgendes wichtig:

var app = angular.module('myApp', [
  'ngRoute', 'ngAnimate'
]);

Ein Angular Modul namens myApp wird erstellt. Es benötigt ngRoute für das Erstellen des Menüs und ngAnimate für den Effekt des Einfadens der geladenen Inhalte. Gespeichert wird das Modul in der Variable „app“.

Für das Laden der Inhalte benötigen wir nun lediglich noch folgenden Code in der app.js:

app.config(['$routeProvider', function ($routeProvider) {
  $routeProvider
    // Home
    .when("/", {templateUrl: "partials/work.html"})
    // Pages
    .when("/about", {templateUrl: "partials/about.html"})
    .when("/referenzen", {templateUrl: "partials/referenzen.html", controller: "ReferenzenCtrl"})
    .otherwise({redirectTo: '/'}) 
}]);

Das ist im Prinzip schon alles. Wichtig zu erwähnen ist, dass der Effekt beim Anzeigen der Inhalte durch CSS verursacht wird. Sobald „ngAnimate“ eingebunden wird, stehen diverse CSS Klassen zur Verfügung. Der <div ng-view> bekommt daher die Klasse fade-animate, so dass durch folgendes CSS der gewünschte Effekt erzielt werden kann:

.fade-animate.ng-enter {
  -webkit-transition: all 1.5s ease;
  -moz-transition: all 1.5s ease;
  -ms-transition: all 1.5s ease;
  -o-transition: all 1.5s ease;
  transition: all 1.5s ease;
  -webkit-opacity: 0;
  opacity: 0;
 }
.fade-animate.ng-enter.ng-enter-active {
  -webkit-opacity: 1;
  -moz-opacity: 1;
  opacity: 1;
}
.fade-animate.ng-leave.ng-leave-active {
  -webkit-opacity: 0;
  -moz-opacity: 0;
  opacity: 0;
}

Ein funktionierendes Beispiel ist meine eigene Website. Im zweiten Teil werde ich das Darstellen, Sortieren und Filtern einer Projektliste beschreiben.

Angular App und SEO / google Indexierung

Google hat ja angekündigt, dass das Indexieren von Webseiten, deren Content durch JavaScript erzeugt wird, mittlerweile funktioniert, ohne dass der Webmaster zu weiteren Maßnahmen greifen muss (http://googlewebmastercentral.blogspot.de/2014/05/understanding-web-pages-better.html).

Wenn man in den google Webmastertools überprüft, ob und wie google die Site indexiert („Crawling“ / „Abruf wie durch google“) so stellt man fest, dass google die dynamisch erzeugten Inhalte nicht findet, wenn die Angular Bibliothek über ein CDN eingebunden wird (<script src="http://code.angularjs.org/1.2.28/angular.js"></script>. Google meldet dann, dass diese Datei „blockiert“ wurde und zeigt lediglich eine leere Seite an. Legt man die Datei dagegen auf dem eigenen Server ab und ruft diese von dort auf, so klappt die Indexierung.

Hinweis: die Webmastertools sind an dieser Stelle nicht ganz selbsterklärend: man muss, nachdem man man auf „Abrufen und Rendern“ geklickt hat, als nächstes in die neu entstandene Tabellenzeile klicken, um das, was google indexiert hat, zu sehen. Hier findet sich auch der eventuelle Hinweis auf das Blockieren einiger Ressourcen.

Weiterer Hinweis: Wenn man bei google nach der Angular Site sucht und sich in den Suchergebnissen anschaut, was bei „Im Cache“ steht, so sieht man dort eine leere Seite. Offenbar kann der google Cache die Seiteninhalte nicht anzeigen, obwohl die Inhalte indexiert sind.

Links
docs.angularjs.org/tutorial
www.codeschool.com/courses/shaping-up-with-angular-js
www.interaktionsdesigner.de/2013/ein-einstieg-in-angularjs/