【问题标题】:How to invoke multiple functions/chained calls using ng-click如何使用 ng-click 调用多个函数/链式调用
【发布时间】:2015-02-27 01:32:29
【问题描述】:

您好,我有一个按钮可以触发两个类似的功能。有没有办法让 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();
    }

【问题讨论】:

  • 从技术上讲,如果你的调用返回一个承诺,你可以内联编写,你在 configuratorService.addOption 内部做什么操作?
  • @PSL 我正在做一个看跌期权
  • 如果你从你的服务返回一个承诺,你可以将它内联写在视图中,而不是传递一个回调。如果你愿意,我可以举个例子。

标签: javascript html angularjs function angularjs-controller


【解决方案1】:

从技术上讲,如果changeColor 返回承诺,您可以编写内联代码,然后您的服务调用必须返回一个承诺(无论如何,这比传统的传递回调更好)。

首先改变你的服务返回一个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
          });
     }
  }

在颜色控件中:

$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 答案中提供的一个问题是,您的控制器之间变得紧密耦合,可能会影响可重用性,您需要在测试 ColorsCtrl 时进行额外的模拟以添加不存在的方法 updateDetails

虽然我的回答中的这种方法有其自身的问题,因为现在您的视图需要知道一些它不应该知道的东西(该方法返回承诺)。还有其他方法可以更好地处理这种情况:一种简单的方法是使用事件或发布/订阅模式,它通知其他控制器这里发生了一些事情,做任何你想做的事情。这种设计将使其更松散耦合,更可重用和可测试。

您可以根据适用性结合 $on 使用角度事件总线本身,例如 $broadcast$emit , 来执行这个任务,或者你可以创建一个pub/sub design yourself

通过简单的事件,您只需这样做:-

在颜色控件中:

    $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");                           
          });
       }
   }

在HeaderCtrl中订阅一个事件并注册updateDetails方法:

//....
$scope.updateDetails = function(){
    $scope.summaryDetails = getSummaryDetails();
}


//...
$scope.$on("Configuration_Udpated", $scope.updateDetails)

旁注:- 尝试使用 promises 而不是将回调传递给服务。您可以在网上找到很多关于 promise patterns 的文章。

【讨论】:

  • 感谢您的回复,解决了很多问题。我使用了 $broadcast 和 $on,效果非常棒!
【解决方案2】:

由于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);"

【讨论】:

  • 恕我直言,这种方法是为了让它工作,但它确实使控制器紧密耦合,并且会严重影响可重用性和可测试性。
猜你喜欢
  • 1970-01-01
  • 2018-09-28
  • 2018-02-07
  • 1970-01-01
  • 1970-01-01
  • 2017-08-21
  • 2013-07-09
  • 1970-01-01
  • 2017-10-08
相关资源
最近更新 更多