Globale Variable mit Angular

Ein Set von global gültigen Variablen legt man gerne in eine static oder shared Klasse. Wer bereits mit ASP.NET gearbeitet hat, weiß, dass dies nicht so einfach ist. Noch schwieriger wird es mit Masterpage (Webforms) oder Layout Pages (MVC). In beiden Fällen werden aus mindestens zwei Dateien Vorlagen und Inhalt vereint.

Es erscheint wenig sinnvoll einen einzigen Controller in die Masterpage zu legen und darin die Logik aller Content Pages einzubauen. Folglich wird man einen  Controller für die Masterpage definieren und einen für jede Content Page. Bleibt die Frage, wie diese miteinander sprechen und wie man Daten im Sinne einer globalen Variable austauscht. Wir müssen den Connection-Status einer Websockets-Verbindung an vielen Stellen prüfen können.

Um gemeinsam nutzbaren Code und damit auch eine Variable anlegen zu können, sieht Angular einen Service, Factory oder Provider vor.  Die Factory erhält den Namen global und liefert den Connection Status mit false zurück.

   1:  App.factory('global', function () {
   2:      var global = {
   3:          isConnected: false
   4:      };
   5:      return global;
   6:  });

Per Depedency Injection wird die Factory im Controller verfügbar. Konkret werden alle Objekte in den Funktonsaufruf des Controllers gepackt, hier der $scope für das Viewmodel und die Factory global.

Die Direktive enthält noch eine Command-Funktion, um den Status ändern zu können.

   1:  app.controller('contentController', function($scope,global) {
   2:    $scope.isConnected = global.isConnected;
   3:    $scope.connect=function()
   4:    {
   5:   
   6:      $scope.isConnected=global.isConnected=true;;
   7:    }
   8:  });

Gebunden wird das Angular typischerweise im HTML Code, in der Praxis in der Content Page.

   1:  <div  ng-controller="contentController">
   2:    Content Page Dingens
   3:      
   4:       <p>Status {{isConnected}}!</p>
   5:       <button ng-click="connect()">connect</button>
   6:    </div>

 

In der Masterpage wird ein eigener Controller definiert, der z.B. Elemente im Menübereich bindbar hält. Der JavaScript-Code unterscheidet sich auf den ersten Blick nicht vom vorigen Codebeispiel. Allerdings muss der Main Controller die Änderung in global.isConnected auch mitgeteilt bekommen. Dazu kann man einen Watcher einrichten, der die Änderung des Wertes zum Anlass nimmt, den lokalen Scope neu zu schreiben.

   1:  app.controller('mainController', function($scope,global) {
   2:   
   3:    $scope.isConnected = global.isConnected;
   4:    
   5:     $scope.$watch(
   6:          function(){ return global.isConnected},
   7:   
   8:          function(newVal) {
   9:            $scope.isConnected = newVal;
  10:          }
  11:        )
  12:   
  13:  });

 

Das lauffähige Sample.

Sehr oft sieht man für diese Aufgabenstellung auch einen Ansatz mit Broadcast auf den $rootscope. Dieser erfordert deutlich mehr Code. Alternativ kann man auch im $Rootscope eine Variable nutzen, davor wird jedoch allerseits gewarnt.

Kommentare sind geschlossen