$ resource promise结算时更新$ scope

时间:2014-11-16 11:41:57

标签: angularjs angularjs-scope angularjs-ng-click angular-promise angularjs-view

我一直试图正确地探讨如何正确使用angular $ scope。我的应用程序根据加载主页时从服务器收到的json数据中的URL链接更新视图。

控制器在单击按钮时获取下一个数据文件,但我无法将此数据注入我的范围变量并更新视图。网络成功传输数据,因此我的服务正在运行。

我不明白如何让$ scope解析$ resource promise并在应用初始化后检索数据时更新视图。非常感谢有关此事的任何帮助。

我的ListController:

//View updates correctly when promise resolves
$scope.data = DataElements.get({}); 

$scope.nextPage = function (){ //Called when clicking 'next' button
var url = $scope.data.pager.nextPage; 

var pageNumber = url.split("page=").pop(); //Ugly but it is temporary, I promise..

//View doesnt update
DataElements.get({'page': pageNumber}, function(data){ 
    $scope.data = data; 
});

//Error: Digest already in progress
DataElements.get({'page': pageNumber }, function(data){ 
    $scope.$apply(function(){
      $scope.data = data; 
    });
});

//View doesnt update
$scope.data = DataElements.get({'page': pageNumber)};  

};

服务:

services.factory('DataElements', ['$rootScope','$resource', function($rootScope, $resource){
    return $resource($rootScope.baseUrl+'api/:endPointAdr.jsonp', 
        {'endPointAdr': 'dataElements', 'page': '@page'}, 
        { get : {'method' : 'JSONP', 'params' : {'callback' : 'JSON_CALLBACK'}}     
    });
}]);

查看:

<section>
  <div>
    <h1>Search</h1>
    <input type="text" placeholder="Type something" autofocus>
    <input type="button" name="filter" value="Filter">
    <input type="button" name="clear" value="Clear">
    <div class="btn-toolbar" role="toolbar" aria-label="...">
      <a class="btn btn-default" href="#" aria-label="Previous Page">
        <span class="glyphicon glyphicon-chevron-left"></span>
      </a>
      <a class="btn btn-default" href="#" ng-click="nextPage()" aria-label="Next Page">
        <span class="glyphicon glyphicon-chevron-right"></span>
      </a>
    </div>
  </div>
  <div ng-controller="ListController">
    <ul class="" ng-show="data">
      <li class="" ng-repeat="element in data.dataElements ">
        <a href="#">
          <div class="info">
            <h2>{{element.name}}</h2>
          </div>
        </a>
      </li>
    </ul>
  </div>
</section>

服务器响应:

DataElements.get({}) == >
angular.callbacks._1({"pager": {"page":1,"pageCount":15,"total":706,"nextPage":"http// ...});(*)

DataElements.get({'page': 2})  == > 
angular.callbacks._2({"pager": {"page":2,"pageCount":15,"total":706,"nextPage":"http:// ...});(*)

(*)$ resource剥离jsonp并仅返回json。

更新:

如果我只在$scope.data功能范围内指定nextPage,它就能完美运行。我知道ng-click指令在$scope.apply()中包含了这个函数。然后明确调用apply会导致错误。

解决方案:

<div ng-controller="ListController">创建了一个具有不同$ scope的重复控制器。删除它修复了问题。有关详细信息,请参阅我的回答。

3 个答案:

答案 0 :(得分:1)

如果DataElements.get返回一个promise对象,则需要调用then方法:

DataElements.get({'page': pageNumber}).then(function(data) {
   $scope.data = data;
})

或者如果它使用$ resource通常会返回一个具有$promise属性的对象:

DataElements.get({'page': pageNumber}).$promise.then(function(data) {
   $scope.data = data;
})

答案 1 :(得分:1)

我终于解决了这个问题。

归结为这个<div ng-controller="ListController">指令。它创建了第二个ListController并将其附加到$rootScope。绑定没有任何问题,但nextPage()是从不同的范围调用的。

在动态ListController的初始化阶段,两个控制器都会执行DataElements.get..,这就是它似乎工作的原因,但调用ng-click : nextPage()并没有在分配给它的控制器的上下文中运行list.html图。

答案 2 :(得分:0)

正如您所提到的,$scope上的数据正在更新,但更改不会传播到视图。有些事情打破了双向约束。

查看您在控制台中获得的错误类型(Chrome中的F12)。

删除此代码块:

//Error: Digest already in progress
DataElements.get({'page': pageNumber }, function(data){ 
    $scope.$apply(function(){
      $scope.data = data; 
    });
});

//View doesnt update
$scope.data = DataElements.get({'page': pageNumber)};  

明确避免使用$apply,这很少是一个好主意。

修改

尽管OP通过删除ListController的绑定来解决他的问题以避免$scope混淆,但HTML代码看起来有点奇怪,就像现在一样。最佳解决方案是创建绑定到ListController的指令,然后在视图中重用此指令。这样,OP将来会避免此类$scope问题。