如何在具有隔离范围的指令上使用 ng-click? [英] How can I use ng-click on a directive with isolate scope?

查看:26
本文介绍了如何在具有隔离范围的指令上使用 ng-click?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当作用域是在指令上继承时,我可以让 ng-click 工作,但在隔离时不能.更新:关键是我希望将点击函数定义为指令的一部分......将函数定义移动到不同的范围并不是我想要的.

这是具有继承范围的工作示例:https://codepen.io/anon/pen/PGBQvj

这是具有隔离作用域的破碎示例;https://codepen.io/anon/pen/jrpkjp

(单击数字,它们在第一个示例中递增,但在第二个示例中没有)

一些代码...

HTML

<my-directive ng-click="hello()" current="current"></my-directive>

具有继承范围的指令:

angular.module('myApp', []).controller('baseController', function($scope) {$scope.current = 1;}).directive('myDirective', function() {返回 {链接:函数(范围,元素,属性){scope.hello = 函数(){范围.current++};},替换:真的,范围:真实,模板:'<div><child><strong>{{ current }}</strong></child></div>'}}).directive('child', function() {返回 {链接:函数(范围,元素,属性){console.log("horeee");}}});

相同的指令但具有独立的作用域:

angular.module('myApp', []).controller('baseController', function($scope) {$scope.current = 1;}).directive('myDirective', function() {返回 {链接:函数(范围,元素,属性){scope.hello = 函数(){范围.current++};},替换:真的,范围: {当前:'='},模板:'<div><child><strong>{{ current }}</strong></child></div>'}}).directive('child', function() {返回 {链接:函数(范围,元素,属性){console.log("horeee");}}});

解决方案

问题是您试图调用未定义的函数.如果您希望在隔离指令中定义逻辑,则无需传入函数引用.

<my-directive current="current"></my-directive>

您不能在此处传递 ng-click="hello()".这是控制器的作用域,所以 hello() 是未定义的.

相反,将 ng-click 事件移动到指令的模板

模板:'

补充一点:您正在使用指令的 link() 函数.这是为 DOM 操作保留的.相反,在 controller 函数中定义 hello().

控制器:函数($scope){$scope.hello = function() {$scope.current++}},

不过,我认为这里存在一个更大的架构问题.隔离指令或组件的重点是封装自身内部的逻辑.它不应该操纵外部状态.在这个例子中,你增加了一个数字.如果在应用程序的另一部分,您希望减少一个数字怎么办?使用递减逻辑复制指令会导致大量代码重复.

相反,您应该在控制器中定义递增或递减功能,并将其传递给指令.

<my-directive change-number="increment()" current="current"></my-directive>

然后,使用 & 语法将函数引用绑定到指令:

范围:{当前:'=',更改编号:'&'},

并从模板中调用 changeNumber.这样做非常有利于代码重用.

I can get ng-click to work when the scope is inherited on a directive but not when isolated. UPDATE: The point is that I want the click function to be defined as part of the directive... moving the function definition into a different scope is not what I want.

Here's the working example with inherited scope: https://codepen.io/anon/pen/PGBQvj

Here's the broken example with isolated scope; https://codepen.io/anon/pen/jrpkjp

(Click the numbers, they increment in the first example but not in the second)

Some code...

The HTML

<div ng-app="myApp" ng-controller="baseController">
  <my-directive ng-click="hello()" current="current"></my-directive>
</div>

The directive with inherited scope:

angular.module('myApp', [])
    .controller('baseController', function($scope) {
    $scope.current = 1;
  })
    .directive('myDirective', function() {
    return {
      link: function(scope, element, attrs) {      
        scope.hello = function() {
          scope.current++
        };
      },
      replace: true,
      scope: true,
      template: '<div><child>      <strong>{{ current }}</strong></child></div>'
    }
    })
  .directive('child', function() {
    return {
      link: function(scope, element, attrs) {
        console.log("horeee");
      }
    }
  });

The same directive but with isolated scope:

angular.module('myApp', [])
    .controller('baseController', function($scope) {
    $scope.current = 1;
  })
    .directive('myDirective', function() {
    return {
      link: function(scope, element, attrs) {      
        scope.hello = function() {
          scope.current++
        };
      },
      replace: true,
      scope: {
        current:'='
      },
      template: '<div><child>      <strong>{{ current }}</strong></child></div>'
    }
    })
  .directive('child', function() {
    return {
      link: function(scope, element, attrs) {
        console.log("horeee");
      }
    }
  });

解决方案

The problem is you're trying to call a function that is undefined. If you wish the logic to be defined inside the isolated directive, there is no need to pass in a function reference.

<my-directive current="current"></my-directive>

You cannot pass ng-click="hello()" here. This is the scope of the controller, so hello() is undefined.

Instead, move the ng-click event to the template of the directive

template: '<div ng-click="hello()">

One additional point: You're using the link() function of the directive. This is reserved for DOM manipulation. Instead, define hello() within the controller function.

controller: function ($scope) {
  $scope.hello = function() {
      $scope.current++
  }
},

I think there is a larger architectural problem here, though. The point of an isolated directive, or component, is to encapsulate logic internal to itself. It should not manipulate external state. In this example, you're incrementing a number. What if, in another part of your application, you wish to decrement a number? Copying the directive with decrement logic would be a lot of code duplication.

Instead, you should define the increment, or decrement, functionality in the controller, and pass it through to the directive.

<my-directive change-number="increment()" current="current"></my-directive>

Then, use the & syntax to bind the function reference to the directive:

scope: {
  current:'=',
  changeNumber: '&'
},

and call changeNumber from the template. Doing so very much facilitates code reuse.

这篇关于如何在具有隔离范围的指令上使用 ng-click?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆