2016-03-30 6 views
0

Ich begann mit Angular Material zu arbeiten und habe Schwierigkeiten, ein Problem mit der $scope zu verstehen. apply Funktionalität ... immer wenn ich versuche, die UI über Änderungen zu benachrichtigen, indem Sie apply aufrufen, schlägt es mit einem Fehler fehl. Ich weiß, dass es ähnliche Fragen zu SO gibt, aber in meinem Fall werden die Daten nicht von der scope, sondern von der Controller-Instanz gespeichert ...

Ich verwende auch TypeScript für meine Controller-Implementierung; nicht sicher, aber das scheint ziemlich ungewöhnlich zu sein, da der meiste Beispielcode, den ich gefunden habe, auf einer Inline-Controller-Implementierung in der Ansicht basiert.

Mein Controller so aussieht ...

module MyApp { 

    export class MyController { 

     private scope: angular.IScope; 
     private http: angular.IHttpService; 

     public model: { data: SampleData } = { data: { } }; 

     constructor($scope: angular.IScope, $http: angular.IHttpService) { 
      this.scope = $scope; 
      this.http = $http; 
     } 

     public querySampleData(): void { 

      const serviceEndpoint: string = "http://localhost:8080/api/"; 
      var promise: ng.IHttpPromise<SampleData> = this.http.get(serviceEndpoint + "sample", { }); 

      var callback: ng.IHttpPromiseCallback<SampleData> = (
       data: SampleData, 
       status: number, 
       headers: angular.IHttpHeaderGetter, 
       config: angular.IRequestConfig) => { 
       this.scope.apply(() => { 
        this.model.data = data; 
       }; 
      }; 

      promise.success(callback); 
     } 
    } 

    export interface SampleData { 
     message? string; 
    } 
} 

Der Controller bietet die querySampleData Methode, die einige Daten von einem Remote-Service erhält (es verwendet IHttpService für asynchrone API-Aufrufe). Die Steuerung wird von der Ansicht folgendermaßen verwendet:

<html ng-app="app"> 
    <body ng-controller="MyController as c"> 
     <div> 
      <button ng-click="c.querySampleData()" 
        aria-label="Query sample data">Query sample data</button> 
      <p>{{c.model.data.message}}</p> 
     </div> 
     ... 
     <script src="../scripts/app.js"></script> 
     <script type="text/javascript"> 
      var app = angular.module("app", ["ngMaterial"]); 
      app.controller("MyController", [ "$scope", "$http", MyApp.MyController ]); 
     </script> 
    </body> 
</html> 

Die Initialisierung des Controllers funktioniert einwandfrei; Alle Abhängigkeiten werden ordnungsgemäß in den Controller injiziert und auch die Bindung an die querySampleData Methode funktioniert wie erwartet (wenn ich auf die Schaltfläche klicke, wird die Methode aufgerufen). Wenn ich die empfangenen Daten dem Modell zuweise, wird die Benutzeroberfläche nicht aktualisiert. Daher habe ich der Methode $apply einen Anruf hinzugefügt, um die Benutzeroberfläche über Änderungen zu informieren, was mir den oben erwähnten Fehler gibt.

Update:

Die vorliegende Dokumentation: https://docs.angularjs.org/error/$rootScope/inprog empfiehlt $timeout statt $apply zu verwenden asynchrone Ausführung zu gewährleisten; natürlich korrigiert diese Fehler den Fehler, aber die Benutzeroberfläche nicht ändern ...

Antwort

1

AngularJS Versprechen rufen bereits .apply() (unter der Haube) auf ihre Rückrufe. Sie können .apply nicht erneut in den Callbacks aufrufen, da sie bereits angewendet werden. Der Fehler "In Progress" sagt genau das. Entfernen Sie einfach den .apply Anruf und es funktioniert, es sei denn, Sie haben weitere Fehler.

+0

Okay; Ich habe herausgefunden, warum ich keine Änderungen in der UI gesehen habe ... es war, weil ich den Alias ​​'c' aus seinem Gültigkeitsbereich genommen habe ... blöd mich (-; Ihre Antwort ist richtig; wenn die Bindung in Ordnung ist ... Es ist nicht nötig, 'apply' manuell aufzurufen. – Matze

0

vielleicht können Sie versuchen, this.model.data = data; und dann this.scope.apply();

Verwandte Themen