ng-show和$ scope。$ apply问题

时间:2014-10-08 02:20:29

标签: javascript angularjs angularjs-scope ng-show

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

2 个答案:

答案 0 :(得分:4)

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

当您指定ng-controller指令时,您正在告诉angular使用该特定控制器作为其当前范围。

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

然而,对于您的身体部分,您没有指定正确的控制器。因此,angular并不知道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>

将overlay div移动到将控制器作为上下文的div中,或者尝试使用$ rootScope。

答案 1 :(得分:0)

强制摘要周期而不必担心阶段的最简单方法可能是将var change调用包装在$ timeout函数中:

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

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