Angular 在 ajax 之后更新 $scope 变量未反映在 UI 中
Angular updating $scope variable after ajax is not reflecting in UI
我似乎无法弄清楚这里的问题。
在 ajax 成功响应中,我在当前控制器中设置了一个未反映在 UI 中的值。我发现的一般答案是 运行 和 Angular ajax 函数 and/or 将 $apply 或 $digest 应用于 $scope。 None 个正在运行。
请注意代码中的 {{ 和 }} angular 标签被替换为 <% 和 %>,因为我使用的是 blade tempting 引擎并且这些标签冲突。
想法是在控制器中设置一个处理布尔值。在 ajax 之前设置为 true,之后设置为 false。问题是该值未 returned 到其 false 状态。 运行 $apply 或 $digest 方法都 return Error: [$rootScope:inprog]
.
之后ajax我运行
console.log($scope.processing);
console.log(this.processing);
console.log($scope);
返回
undefind
undefind
return 是 $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;
};
}]);
})();
你的控制器代码应该重置标志
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
}]);
是的,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>
$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 以获得最佳实践 angular 风格。这是最新的指南,甚至 google 本身也引用了它。
我似乎无法弄清楚这里的问题。 在 ajax 成功响应中,我在当前控制器中设置了一个未反映在 UI 中的值。我发现的一般答案是 运行 和 Angular ajax 函数 and/or 将 $apply 或 $digest 应用于 $scope。 None 个正在运行。
请注意代码中的 {{ 和 }} angular 标签被替换为 <% 和 %>,因为我使用的是 blade tempting 引擎并且这些标签冲突。
想法是在控制器中设置一个处理布尔值。在 ajax 之前设置为 true,之后设置为 false。问题是该值未 returned 到其 false 状态。 运行 $apply 或 $digest 方法都 return Error: [$rootScope:inprog]
.
之后ajax我运行
console.log($scope.processing);
console.log(this.processing);
console.log($scope);
返回
undefind
undefind
return 是 $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;
};
}]);
})();
你的控制器代码应该重置标志
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
}]);
是的,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>
变量 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 以获得最佳实践 angular 风格。这是最新的指南,甚至 google 本身也引用了它。