如何将ng-click绑定到自定义指令并调用父函数?

时间:2017-02-07 14:59:09

标签: angularjs custom-directive isolated-scope

我们正在使用Angular 1.4.2,我正在尝试使用ng-click从指令中获取计数值,将其传递给函数,然后将其传递给父控制器。经过一番努力后,它正在使用plunker,但不幸的是,当我尝试将此功能移回主代码时,我无法让控制器绑定到隔离范围。

应该很简单,但我尝试将当前控制器注入指令并尝试创建一个新的控制器,但是当我按下按钮时没有任何反应。

以下是代码:

TEMPLATE:

<!DOCTYPE html>
<html>

  <head>
    <script data-require="angular.js@1.4.2" data-semver="1.4.2" src="https://code.angularjs.org/1.4.2/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>
    <div id="app" ng-app="app">
    <div ng-controller="mainCtrl">
          <my-directive ctrl-fn="ctrlFn(count = count + 10)"></my-directive> 
        </div>
      </div>
  </body>

</html>

SCRIPT:

var app = angular.module('app', []);
app.controller('mainCtrl', function($scope){
  $scope.count = 0;
  $scope.ctrlFn = function() {
      console.log('In mainCtrl ctrlFn!');
      //$scope.count += 10; Old hardcoded value.
      console.log("count is: " + JSON.stringify($scope.count));
    //Call service here
  };  
});

app.directive('myDirective', function() {
  return {
    restrict: 'E',
    scope: {
      'ctrlFn' : '&'
    },
    template: "<div><button ng-click='ctrlFn()'>Click Here</button></div>",
    link: function(scope, element, attributes) {
      scope.ctrlFn(count);
    }
  };
});

以下是我尝试在主代码库中修改的模板代码:

<div>
    <div layout="row">
        <results-loader ctrl-fn="ctrlFn(count = count + 10)"></results-loader>
        <md-button class="md-raised md-primary md-button" ng-click="ctrlFn()" flex>Click Me</md-button>
    </div>
</div>

这里是我在指令中使用现有控制器作为父控制器的地方。它在路由中定义,而不是ng-controller,并且已经用于此视图。

myresultsCtrl.$inject = ['$scope', ' myService'];
        /* @ngInject */
        function myresultsCtrl($scope, myService) {
            $scope.count = 0;
etc...

然而,它显然没有被正确绑定,因为我从来没有点击指令或这个功能用ng-click。

就像我说的那样,我尝试在模板中添加一个新的控制器,然后我尝试将现有的控制器注入到指令中,但都没有工作。我从指令中取出模板并尝试使用ctrl-fn将ng-click直接放入模板中,但我不确定如何通过调用ctrl-fn属性来连接点击。在模板中同时使用指令?这里的想法是将模板移动到它自己的html文件中并从指令引用它,如:template:&#34; myFile.html。我试图尽可能地将其封装成可重用的组件。

我没有使用自定义指令。

以下是plunker的直接链接。

2 个答案:

答案 0 :(得分:0)

我不知道您的确切任务,但重新考虑您的架构。为什么要计算指令中的值?在您的简单情况下,最好计算服务或控制器中的值,而不是指令。

在指令中注入控制器是反角度模式。你需要重新考虑你的意图。最好将数字传递给指令,在那里进行计算并将数字发送回控制器。由于双向数据绑定,它可以在没有额外代码的情况下工作。这里是你的plunker的一个分叉: http://plnkr.co/edit/KpB6bv5tHvXSvhErLcEp?p=preview 主要部分是指令的定义: <div><span>{{count}}</span><br /><button ng-click='myFunction()'>Calculate</button></div>

答案 1 :(得分:0)

我不想回答我自己的问题,因为这可能会有负面的外观,但在这种情况下,我不知道我是否能够很好地解释这个问题以获得正确的答案。让我失望的是将我的工作plunker代码集成到我们现有的代码库中。

我遇到的问题是如何为此用例正确设置控制器。虽然我在模块中声明了我的控制器并注入了控制器,因为它已经绑定到该视图,但我需要在指令本身中定义控制器。一旦我把所有三个一起完成,一切都开始有效了。

以下是一些代码段:

angular.module('directiveName', [])
        .directive('directiveName', directiveName)
        .controller('injectedCtrl', injectedCtrl)
        etc...

var directive = {
        restrict: 'E',
        scope: {
            'ctrlFn' : '&'
        },
        template: "<div><button ng-click='ctrlFn()'>Click Here</button></div>",
        controller: "injectedCtrl",
        link: function(scope, element, attributes) {
            scope.ctrlFn(); //This will pass to the parent controller: injectedCtrl, where $scope resides.
        }
    }
    return directive;   
}


injectedCtrl.$inject = ['$scope', 'myService'];
    /* @ngInject */
    function injectedCtrl($scope, myService) {
    $scope.ctrlFn = function() {
        //do something
    }
    etc...

HTML CODE:

当从指令单击按钮时,ctrlFn这里是DDO中我的指令隔离范围下的引用。这将获取传入的外部函数,即:ctrlFn(),然后可以从指令调用它来调用父控制器。

<div layout="row">
        <results-loader ctrlFn="ctrlFn()"></results-loader> 
    </div>

我发布此信息是为了帮助其他可能拥有此用例的人,因为要弄清楚这一点并不容易。

Dah Wahlins的帖子更详细地介绍了这个主题:Creating Custom AngularJS Directives Part 3 - Isolate Scope and Function Parameters以及有助于让我的思维理顺的内容。