ng-if在使用AngularJS准备数据之前调用

时间:2015-07-14 21:48:01

标签: javascript html angularjs

使用Controller作为服务,工厂的所有示例,使用$scope,我有点困惑。我有一个简单的ng-if表达式,它返回未定义,因为要评估的数据还没有准备好:

<div ng-if="ctrl.AlreadyBoughtShoe('ShoeId')"> ... </div>

  ...

<script>
  (function() {

    var MyApp = angular.module("MyApp", []);

    MyApp.controller("MyAppController", function($http, $timeout, ShoeService) {
      var x = this

      loadRemoteData();

      function loadRemoteData() {
        ShoeService.GetShoes().then(function(Shoes){
          applyRemoteData(Shoes); 
        });
      }

      function applyRemoteData(Shoes) {
        x.Shoes = Shoes;
      }

      // FAILS HERE - Get undefined on the array
      x.AlreadyBoughtShoe = function(shoeId) {
        for (var i = 0; i < x.Shoes.length; i++) {
            // Do stuff 
        }               
      } 
    });

    MyApp.service("ShoesService", function($http, $q){

      return({
        GetShoes: GetShoes        
      });

      function GetShoes() {

        var request = $http({
            method: "GET",
            url: /MyUrl",
            cache: false,
            headers: $myHeaders            
        });

        return( request.then(handleSuccess, handleError));
      }

      function handleError( response ) {

        if (!angular.isObject(response.data) || !response.data.message) {
          return( $q.reject( "An unknown error occurred." ) );
        }

        return( $q.reject(response.data.message) );

      }

      function handleSuccess( response ) {
        return( response.data );            
      }

    });
  })();

</script>

另外,如果它是相关的,在这种特殊情况下它与鞋子无关......并且数据是人物对象,并且没有ng-repeat继续,所以“鞋子”的ID手动输入。我混淆了我的实际代码以简化这一点,因此我可以理解处理它的最佳方法,但ng-if需要在数据准备好进行评估后进行评估。

我不确定如何最好地使用这种格式的promises或其他任何我需要的东西,我在网上的某个地方找到了一个例子。

4 个答案:

答案 0 :(得分:1)

由于ShoeService中服务调用的异步性质,这种情况正在发生。由于在解析x.Shoes = Shoes之前调用了代码,您的错误正在发生,基本上是在undefined上进行迭代。尝试将您的逻辑移动到服务的then回调中。例如......

function loadRemoteData() {
   ShoeService.GetShoes().then(function(Shoes) {
       applyRemoteData(Shoes); 

       x.AlreadyBoughtShoe = function(shoeId) {
           for (var i = 0; i < x.Shoes.length; i++) {
               // Do stuff 
           }               
       } 
   });
}

如果您愿意,也可以将其移至applyRemoteData的末尾。无论哪种方式,您都需要在解决x.Shoes

后执行此逻辑

答案 1 :(得分:0)

你是对的 - 当这段代码运行时,x.Shoes未定义。变化:

x.AlreadyBoughtShoe = function(shoeId) {
  for (var i = 0; i < x.Shoes.length; i++) {
      // Do stuff 
  }               
} 

为:

x.AlreadyBoughtShoe = function(shoeId) {
  for (var i = 0; i < (x.Shoes || []).length; i++) {
      // Do stuff
  }
}

答案 2 :(得分:0)

您有多种选择。

  1. 默认情况下,将ng-if评估为false,直到您收到数据为止。您保留AlreadyBoughtShoe方法但首先检查是否有数据。如果您没有数据但只是返回false。您不再有错误,当您的承诺得到解决时,您的HTML应该反映出来。

  2. You can delay controller initialization until your promise is resolved.

答案 3 :(得分:0)

也许设置信号量或者simillar可以提供帮助。 Promise在一段时间后进行评估,并在成功调用后将变量设置为true可能会有所帮助。然后将该变量添加到ng-if条件,该条件仅在变量为true时才计算函数,因此返回promise。

将变量设置为和条件,这将在两者都为真时进行评估。

<div ng-if="ctrl.loaded && ctrl.AlreadyBoughtShoe('ShoeId')"> ... </div>

然后在成功时将变量设置为true(由于javascript,默认设置为false)。

  function loadRemoteData() {
        ShoeService.GetShoes().then(function(Shoes){
          x.loaded = true;
          applyRemoteData(Shoes); 
        });
      }

这可能会有所帮助。