在ajax未在UI中反映之后角度更新$ scope变量

时间:2015-05-29 18:23:50

标签: javascript ajax angularjs scope angular-http

我似乎无法在这里弄清楚这个问题。 在ajax成功响应中,我在当前控制器中设置了一个未在UI中反映的值。我发现的一般答案是运行Angular ajax函数和/或将$ apply或$ digest应用于$ scope。这些都不起作用。

请注意代码中{{和}}角度标记替换为<%和%>因为我正在使用刀片诱人引擎,这些标签冲突。

想法是在控制器中设置处理布尔值。在ajax之前设置为true,之后设置为false。问题是值没有返回到false状态。运行$ apply或$ digest方法都返回Error: [$rootScope:inprog]

在我运行ajax之后

console.log($scope.processing); console.log(this.processing); console.log($scope);

返回

undefind undefind 并返回$ scope对象。 但是在控制台输出的$ scope对象中,处理的值应该是(false)。

然而,它没有在UI中反映出它仍然是真的。单击切换按钮可将处理值设置为false,并更新UI。 所以我对问题出在哪里感到非常困惑......

HTML

<div class="panel panel-default" ng-controller="UnitOfMeasureController as uom">
          <div class="panel-heading">
            <h3 class="panel-title">Create new Unit of Measure</h3>
          </div>
          <div class="panel-body">
            <div ng-hide="uom.processing">
           <form ng-submit="uom.processForm()" id="new_uom_form">
              <div class="form-group">
                <label for="uom_input01">Name</label>
                <input ng-model="uom.formData['name']" type="text" class="form-control" id="uom_input01" placeholder="" name="uom[input01]" value="{{\xsds::old('uom.input01',$values)}}">
              </div>
               <div style="text-align:right"><button type="submit" class="btn btn-primary" ><i class="fa fa-plus-square"></i> Create new Unit of Measure</button></div>
                </form> 
                </div>
                {!!\xsds::angularLoader('ng-show="uom.processing"')!!}
            </div>
            <button ng-click="uom.processing = false">Toggle</button>
            <%uom.processing%>
        </div>

app.js

(function( ){
var app = angular.module('ingredients',[], function($interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
}); 


app.controller('UnitOfMeasureController', ['$scope','$http', function($scope,$http) {
formData = [];
this.processing = false;
this.processForm = function( ){
    this.processing = true;

    $http.get(document.js_root+'/recipe/ingredients/uom/ajax-create').
      success(function(data, status, headers, config) {
         /* $scope.$apply(function(){
              $scope.processing = false;
            });*/
          console.log($scope.processing);
          console.log(this.processing);
          console.log($scope);

          $scope.processing = false;
          if (!data.success) {  
              console.log(data.errors);
          } else {
              console.log('success');
          }

          //$scope.$digest();
          //$scope.$apply(); similar but slower
        /*  $scope.$apply(function() {
              $scope.processing = false;
            });*/
      }).
      error(function(data, status, headers, config) {
          $scope.processing = false;
         if(document.is_js_dev){
             alert(status+' ');
         }            
      });       

     return false;
};
}]);



})();

3 个答案:

答案 0 :(得分:0)

你的控制器代码应该重置标志 使用this.processing = false;语法时,$scope.processing = false;代替controllerAs

另外使用var vm = this;然后使用vm代替this

<强>控制器

app.controller('UnitOfMeasureController', ['$scope','$http', function($scope,$http) {
   var vm = this;
   //then use this in your controller instead of this
}]);

答案 1 :(得分:0)

是的,var vm = this;是一种方式。

或者您可以在成功或错误方法中使用.bind(this)。使用ES6,您可以使用arrow functions

请查看此jsfiddle。同样的演示如下。

var app = angular.module('ingredients', [], function ($interpolateProvider) {
    $interpolateProvider.startSymbol('<%');
    $interpolateProvider.endSymbol('%>');
});


app.controller('UnitOfMeasureController', ['$scope', '$http', function ($scope, $http) {
    formData = [];
    this.processing = false;
    this.processForm = function () {
        this.processing = true;
        
        var onSuccess = function (data, status, headers, config) {
            /* $scope.$apply(function(){
              $scope.processing = false;
            });*/
            //console.log($scope.processing);
            console.log(this.processing);
            //console.log($scope);

            this.processing = false;
            /*if (!data.success) {
                console.log(data.errors);
            } else {*/
            console.log('success', data);
            //}

            //$scope.$digest();
            //$scope.$apply(); similar but slower
            /*  $scope.$apply(function() {
              $scope.processing = false;
            });*/
        };
        
        var onError = function (data, status, headers, config) {
            this.processing = false;
            if (document.is_js_dev) {
                alert(status + ' ');
            }
        };
        
        $http.jsonp('http://www.mocky.io/v2/5568b30150223de60c64f24f/?callback=JSON_CALLBACK').//document.js_root + '/recipe/ingredients/uom/ajax-create').
        success(onSuccess.bind(this)).
        error(onError.bind(this));

        return false;
    };
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="panel panel-default" ng-app="ingredients" ng-controller="UnitOfMeasureController as uom">
    <div class="panel-heading">
         <h3 class="panel-title">Create new Unit of Measure</h3>

    </div>
    <div class="panel-body">
        <div ng-hide="uom.processing">
            <form ng-submit="uom.processForm()" id="new_uom_form">
                <div class="form-group">
                    <label for="uom_input01">Name</label>
                    <input ng-model="uom.formData['name']" type="text" class="form-control" id="uom_input01" placeholder="" name="uom[input01]" value="{{\xsds::old('uom.input01',$values)}}">
                </div>
                <div style="text-align:right">
                    <button type="submit" class="btn btn-primary"><i class="fa fa-plus-square"></i> Create new Unit of Measure</button>
                </div>
            </form>
        </div><!--{!!\xsds::angularLoader('ng-show="uom.processing"')!!}</div>-->
    <button ng-click="uom.processing = !uom.processing">Toggle</button>
    <%uom.processing%>
</div>

答案 2 :(得分:0)

$ http.get成功函数中的

变量this可能不再是您想要的this。事实上,this可能是somebody that you used to know,但现在你忘记了!

我已修改您的演示代码

 app.controller('UnitOfMeasureController', [
    '$scope',
    '$http', 
    UnitOfMeasureController
]);

function UnitOfMeasureController($scope,$http) {
    var vm = this;
    vm.processing = false;
    vm.processForm  = processForm;

    function processForm(){
        vm.processing = true;

        var url = document.js_root+'/recipe/ingredients/uom/ajax-create';
        return $http
            .get(url)
            .success(function() {
                vm.processing = false;   
            })
            .error(function(err) {
                vm.processing = false;
            });        
    };
}

但我认为您应该将$ http.get部分移动到服务,例如RecipeService或您想要的任何名称。

查看https://github.com/johnpapa/angular-styleguide最佳练习角度风格。这是谷歌本身所指的最新指南。