2014-10-08 31 views
0

在HTML上,我有一个覆盖div来显示使用指令ng-show="showLoading"的加载进度。在模板ng-click上我打电话给控制器searchRequest方法。此方法在发出http请求之前将showLoading更新为true。

如果我这样做,加载不会显示,如果我使用$scope.$apply来更新变量,那么我得到$apply already in progress错误消息。到底是怎么回事?我应该怎么做?

这是index.html的

<!DOCTYPE html> 
<html> 
    <head> 
    <meta charset="utf-8"> 
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"> 
    <title></title> 

    <link href="lib/ionic/css/ionic.css" rel="stylesheet"> 
    <link href="css/style.css" rel="stylesheet"> 

    <!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above 
    <link href="css/ionic.app.css" rel="stylesheet"> 
    --> 

    <!-- ionic/angularjs js --> 
    <script src="lib/ionic/js/ionic.bundle.js"></script> 

    <!-- cordova script (this will be a 404 during development) --> 
    <script src="cordova.js"></script> 
    <script src="js/angular-route.js" ></script> 

    <!-- your app's js --> 
    <script src="js/searchController.js"></script> 
    <script src="js/app.js"></script> 

    </head> 
    <body ng-app="myApp" ng-init="showLoading = false"> 
    <div id="overlay" ng-show="showLoading"> 
     <img id="loading" src="img/ajax-spinner.gif" /> 
    </div> 
    <div ng-view></div> 
    </body> 
</html> 

模板:

<div ng-controller="searchController as searchController"> 
    <ion-header-bar class="bar-stable"> 
    <h1 class="title">Movie Searcher</h1> 
    </ion-header-bar> 
    <ion-content> 
    <label class="item item-input"> 
     <span class="input-label">Title</span> 
     <input style="border-style: solid;border-width: 1px;" type="text" ng-model="searchController.searchString" required> 
    </label> 

    <button class="btn" ng-click="searchController.search()">Search</button> 

    {{response}} 
    </ion-content> 
</div> 

而且控制器:

this.searchRequest = function(url) { 
$scope.showLoading = true; 

$http.get(url).success(function(data) { 
    $scope.showLoading = false; 
    //console.log("Success: " + JSON.stringify(data)); 
    $scope.response = JSON.stringify(data); 
    for (i=0; i<data.length; i++) { 
     var movie = data[i]; 
     //console.log("Movie: " + movie); 
     var genres = ''; 
     for (j=0; j<movie.genres.length; j++) { 
      genres += movie.genres[j]; 
      if (j < movie.genres.length - 1) { 
       genres += ', '; 
      } 
     } 

     console.log("Title: " + movie.title); 
     console.log("Plot: " + movie.simplePlot); 
     console.log("genres: " + genres); 
    } 
}) 
.error(function(data, status, headers, config) { 
    $scope.showLoading = false; 
    $scope.response = "Error: " + status; 
})}; 
+1

我在控制器上看不到'search'方法,也没有提及'$ scope。$ apply'。我建议你尽量减少相关的代码片段并把它放在一个[jsfiddle](http://jsfiddle.net/)中,这样人们(甚至你自己)都有很好的机会来玩弄它,了解你的代码中发生了什么。 – Domi 2014-10-08 02:25:43

+1

搜索方法只是创建url并调用searchRequest方法,我试图只把相关的代码搞砸了:-P无论如何,如何把它放在一个jsfiddle?我有2个js,1个用于路由,另一个是这个控制器,我可以将它们都粘贴到jsfiddle的JS框中吗? – momo 2014-10-08 02:41:35

+1

如果您正在寻找泛型覆盖,并且希望避免在每个ajax调用上维护showLoading属性,那么使用http拦截器可以很好地实现(从最开始)来自Dan Wahlin。检查出来.. https://github.com/DanWahlin/AngularOverlay/blob/master/app/directives/wcAngularOverlay.js – PSL 2014-10-08 02:57:38

回答

4

您的覆盖div没有右侧控制器的数据上下文。

当您指定ng控制器指令时,您告诉角度使用该特定控制器作为其当前范围。

<div ng-controller="searchController as searchController"> 

鉴于你的身体部分在这里,你没有指定正确的控制器。所以,角度不知道showloading属性来自哪里。

<body ng-app="myApp" ng-init="showLoading = false"> 
    <div id="overlay" ng-show="showLoading"> 
     <img id="loading" src="img/ajax-spinner.gif" /> 
    </div> 
    <div ng-view></div> 
    </body> 

要么将​​覆盖div移动到具有控制器作为上下文的div中,要么尝试使用$ rootScope代替。

+0

非常感谢,很好的解释和建议。使用$ rootScope做了诀窍。 – momo 2014-10-08 02:37:44

0

可能迫使摘要周期,而无需最简单的方法担心阶段是在$ timeout函数内部封装var change调用:

$timeout(function() { 
    $scope.showLoading = true; 
}, 0); 
$http.get(url).success(function(data) { 
... 

当然,不要忘记在控制器中注入$ timeout作为依赖。

+0

谢谢,已经试过,但没有工作,因为@克里希纳说,这是所有关于控制器范围 – momo 2014-10-08 02:36:41

+1

足够公平。出于某种原因,我明白它的工作,否则,只是不是当这个http调用之后。 – Shomz 2014-10-08 02:46:20

相关问题