Scroll zum Ende der Seite mit Angular.js

Angular arbeitet ähnlich wie Silverlight mit einem ViewModel. Eine Liste kann so an einen Service gebunden werden, ohne dass das UI blockiert wird. Die Daten kommen eben asynchron.

Im Beispiel sind die Daten länger als der Anzeigeplatz im Browser und man möchte automatisch ans Ende der Liste scrollen. Hier ergeben sich mehrere Detailprobleme:

  • Wann ist die Liste geladen und gerendert?
  • Wie komme ich aus dem Viewmodel in den View?

Durchaus enttäuschend ist die Antwort auf Teil 1. Man weiß nicht, wann die Liste geladen und gerendert ist. Es gibt kein rendered oder loaded Event. Man kann allerdings mit einer Direktive ein HTML Element erweitern. Von der Funktion erschient mir das ähnlich eines Expression Blend Behaviours. Platt gesprochen erstellt man damit neue HTML Attribute. Angular nennt die Funktion Directive. Quasi alles aus Angular setzt auf dieses System (z.B. ng-repeat).

Teil 2 dreht sich darum, wie man aus dem Viewmodel scrollt, ohne in den HTML View JavaScript Code schreiben zu müssen. Dafür bietet Angular eine Methode anchorScroll, die mit einer vorgelagerten Methode Scope das Element wählt und dann den Browser Scroll ausführt.

Die Direktive wird ähnlich wie der Controller im App Modul erzeugt und beim Erreichen des letzten Elements ausgeführt.

   1:  angular.module('kundenApp', [])
   2:    .directive('myRepeatFinished', function ($location,$anchorScroll) {
   3:        return function (scope, element, attrs) {
   4:             if (scope.$last) {
   5:                 $location.hash('pageButton');
   6:                 $anchorScroll();
   7:   
   8:            }
   9:        };
  10:    })

Der Name der Direktive sollte nicht mit ng beginnen, um Konflikte mit dem Angular-Namensraum zu vermeiden. Per Konvention wird bei jedem Wechsel von Klein- auf Großbuchstaben ein Bindestrich eingefügt und der gesamte Name in Lowercase gewandelt.

Im HTML5-Teil wird dann dieses neue HTML-Attribut eingefügt und so das DIV um Funktion, CSS oder ein HTML-Template erweitert.

   1:   <div ng-repeat="kunde in kunden" my-repeat-finished>
   2:              {{kunde.CompanyName}}
   3:   </div>

 

Dieses Beispiel zeigt zur Laufzeit für einen Sekundenbruchteil das JavaScript-Objekt an:

image

Dann erst die eigentlichen Werte:

image

Vermutlich ist die Methode, auf den letzten generierten Eintrag zu setzen, einen Tick zu früh.

Kommentare sind geschlossen