2016-03-30 3 views
0

Я начал работать с Angular Material и с трудом понимаю проблему с $scope. apply функциональность ... всякий раз, когда я пытаюсь уведомить пользовательский интерфейс об изменениях, вызывая apply, он не работает с ошибкой. Я знаю, что есть похожие вопросы по SO, но в моем случае данные не сохраняются scope, а экземпляром контроллера ...

Я также использую TypeScript для реализации моего контроллера; не уверен, но это кажется довольно необычным, так как большинство примеров кода, которые я нашел, основаны на встроенной реализации контроллера прямо в представлении.

Мой контроллер выглядит так ...

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; 
    } 
} 

Контроллер обеспечивает querySampleData метод, который получает некоторые данные из удаленной службы (он использует IHttpService для асинхронных вызовов API). Контроллер используется по виду следующим образом:

<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> 

Инициализация контроллера работает нормально; все зависимости получают должным образом впрыснутые в контроллер, а также привязка к методу querySampleData работает как ожидалось (когда я нажимаю кнопку, вызываемую методом). Если я назначу полученные данные модели, пользовательский интерфейс не будет обновлен, поэтому я добавил вызов метода $apply, чтобы информировать пользовательский интерфейс об изменениях ..., который дает мне ошибку, о которой я упоминал выше.

Update:

Документация по адресу: https://docs.angularjs.org/error/$rootScope/inprog рекомендует использовать $timeout вместо $apply для обеспечения асинхронного выполнения; конечно, это исправляет ошибку, но интерфейс не меняется ...

ответ

1

AngularJS обещает уже называют .apply() (под капотом) на их обратных вызовов. Вы не можете снова вызвать .apply внутри обратных вызовов, так как они уже были .applied, и ошибка «In Progress» сообщает именно об этом. Просто удалите вызов .apply, и он будет работать, если у вас нет дополнительных ошибок.

+0

Okay; Я понял, почему я не видел никаких изменений в пользовательском интерфейсе ... это было из-за того, что я использовал псевдоним 'c' из своего объема ... глупо меня (-; ваш ответ правильный, если привязка прекрасна, s не нужно вручную называть 'apply'. – Matze

0

может быть, вы можете попробовать this.model.data = data;, а затем this.scope.apply();

Смежные вопросы