嗨,我有一个按钮可以触发两个这样的功能。有没有办法让updateDetails只在changeColor完成后才能运行? updateDetails目前正在使用旧颜色拉旧配置,而不是更改颜色。
ng-click="changeColor(color.code); updateDetails()"
以下是观点:
<div ng-controller="ColorsCtrl">
<div ng-controller="HeaderCtrl">
<div byo-header>
</div>
<div ng-repeat="color in colors" class="row">
<div class="small-12 columns">
<div ng-controller="ButtonsController">
<div class="button-group">
{{ isSelected(color.code) }}
<button ng-click="changeColor(color.code); updateDetails()" type="radio" class="button" ng-model="selectedColor" btn-radio="color.code">{{color.name}}</button>
</div>
</div>
</div>
</div>
<br/>
<br/>
<div class="row">
<div class="small-4 small-offset-4 columns">
<!-- Proceed to packages if available -->
<a ng-if="hasPackage" href="#/packages/{{modelCode}}" class="button">Packages</a>
<!-- Proceed to options if packages not available -->
<a ng-if="!hasPackage" href="#/options/{{modelCode}}" class="button">Options</a>
</div>
</div>
</div>
</div>
这是ColorsCtrl中的changeColor():
$scope.changeColor = function(newColorCode){
//swap previous selected color with new
configuratorService.addOption($scope.modelCode, newColorCode, function(configuration){
$scope.configuration = configuration;
});
}
}
这是HeaderCtrl中的updateDetails
$scope.updateDetails = function(){
$scope.summaryDetails = getSummaryDetails();
}
答案 0 :(得分:6)
由于changeColor
是异步操作 - 否,您无法内联等待。您必须在回调中调用该函数:
$scope.changeColor = function(newColorCode){
//swap previous selected color with new
configuratorService.addOption($scope.modelCode, newColorCode, function(configuration){
$scope.configuration = configuration;
$scope.updateDetails();
});
}
如果在其他地方使用此功能而您并不总是想要调用更新,请传递一个标志参数:
$scope.changeColor = function(newColorCode, shouldUpdate){
//swap previous selected color with new
configuratorService.addOption($scope.modelCode, newColorCode, function(configuration){
$scope.configuration = configuration;
if (shouldUpdate) $scope.updateDetails();
});
}
ng-click="changeColor(color.code, true);"
答案 1 :(得分:4)
从技术上讲,你可以编写内联提供的changeColor
返回promise并且你的服务调用必须返回一个promise(与传统的传递回调相比更好)。
首先更改您的服务以返回承诺,例如: -
function configuratorService($http){
this.addOption = function(modelCode, colorCode){
return $http.post("Addoption", {modelCode:modelCode, colorCode:colorCode})
.then(function(response){
//logic to get configuration or whatever
return response.data
});
}
}
在ColorsCtrl中:
$scope.changeColor = function(newColorCode){
//return promise
return configuratorService.addOption($scope.modelCode, newColorCode)
.then( function(configuration){
$scope.configuration = configuration;
/*You could even return the data by doing the following*/
//return $scope.configuration = configuration;
});
}
}
在HeaderCtrl中:
$scope.updateDetails = function(){//<-- if you are returning data from changeColor you could even use it here
$scope.summaryDetails = getSummaryDetails();
}
最后在你看来:
ng-click="changeColor(color.code).then(updateDetails)"
示例演示
angular.module('app', []).controller('HeaderCtrl', function($scope) {
$scope.updateDetails = function() {
//check the console
console.log('UpdateDetails');
$scope.summaryDetails = "Summary Details after option changeColor";
}
}).controller('ColorsCtrl', function($scope, configuratorService) {
$scope.changeColor = function(newColorCode) {
//swap previous selected color with new
return configuratorService.addOption().then(function(configuration) {
//check the console
console.log('Option Added');
$scope.configuration = configuration;
});
}
}).service('configuratorService', function($timeout) {
this.addOption = function() {
//Justa proxy for an ansyn operation and return call
return $timeout(function() {
return "Color Updated"
}, 1000);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="ColorsCtrl">
<div ng-controller="HeaderCtrl">
<button ng-click="changeColor().then(updateDetails)">Update</button>
{{summaryDetails}}
</div>
</div>
还有许多其他选择和更好的方法。在TymeJV答案中提供的一个问题是,你的控制器彼此紧密耦合并可能影响可重用性,你需要做额外的模拟,以便在测试{{1}时添加不存在的方法updateDetails
}}。
虽然我的回答中的这种方法有其自身的问题,因为现在你的视图需要知道某些东西(该方法返回了promise),它不应该。还有其他方法可以更好地处理这种情况:一种简单的方法是使用事件或发布/发布模式,通知其他控制器这里发生的事情做你想做的事情。这种设计将使其更松散地耦合,更可重复使用和可测试。
您可以根据 {{3 }} ,要执行此任务,您可以创建$broadcast。
通过简单的事件你可以这样做: -
在ColorsCtrl中:
ColorsCtrl
在HeaderCtrl中订阅一个事件并注册updateDetails方法:
$scope.changeColor = function(newColorCode){
configuratorService.addOption($scope.modelCode, newColorCode, function(configuration){
$scope.configuration = configuration;
//BroadCast an event, this will notify any child scopes that has subscribed to this event.
$scope.$broadCast("Configuration_Udpated");
});
}
}