angularjs将我自己的函数添加到现有的ng-click中

时间:2014-01-11 05:17:55

标签: angularjs angularjs-directive

我有ng-click="foo()"警告“foo” 在我自己的指令中,如果找到ng-click,我想添加另一个函数来提醒“bar”

我试过这个 演示:http://plnkr.co/edit/1zYl0mSxeLoMU3yjoGBV?p=preview

它不起作用

<!DOCTYPE html>
<html ng-app="myApp">
  <head>
    <script src="http://code.angularjs.org/1.2.7/angular.js"></script>
    <script>
    var app = angular.module('myApp', []);
    app.controller('MyCtrl', function($scope) {
      $scope.foo = function() { alert('foo'); }
      $scope.bar = function() { alert('bar'); }
    });
    app.directive("myAttr", function() {
      return {
        link: function(scope, el, attrs) {
          el.attr('ng-click', attrs.ngClick+';bar()');
        }
      }
    })
    </script>
  </head>

  <body ng-controller="MyCtrl">
    <a my-attr ng-click="foo()" href="">click here!</a>
  </body>
</html>

我也无法使用另一个ng- *指令来使其工作,即el.attr('ng-focus', 'bar()');。似乎在渲染后我无法更改或添加ng- *指令。

我怎样才能做到这一点,我做错了什么?

4 个答案:

答案 0 :(得分:4)

  app.directive("myAttr", function() {
  return {
      priority: 1,
      compile: function(el, attrs) {
       attrs.ngClick += ';bar()';
    }
  }
})

首先,您需要compile函数,因为在调用link时,ng-click指令已经设置。

第二个重要的是改变优先级。您希望确保在ng-click之前调用您的指令。 ng-click的默认优先级为0,因此1就足够了。

最后也是最重要的一点是,你不想改变元素,而是attrs本身。每个元素只创建一次。因此,当ng-click访问它时,如果您直接更改了元素的属性,它仍将包含相同的值。

答案 1 :(得分:2)

我认为你可以用ngTransclude做你想做的事。

app.directive("myAttr", function() {
  return {
    transclude:true,
    template: '<span ng-click="bar()" ng-transclude></span>',
    link: function(scope, el, attrs) {
    }
  }
});

这有用吗?

修改

好的,这个呢?

app.directive("myAttr", function($compile) {
  return {
    link: function(scope, el, attrs) {
      el.attr('ng-click', 'bar()');
      el.removeAttr('my-attr');
      $compile(el)(scope);
    }
  }
});

答案 2 :(得分:2)

虽然这可以通过上面概述的编译来完成,但是这种方法并不能保证ng-click项目被添加到DOM节点的顺序(正如您已经发现的那样),并且本质上很慢(如已经被像贾里德这样的词语指出了。

就个人而言,我会做这样的事情:

  <!DOCTYPE html>
  <html ng-app="myApp">

  <head>
     <link rel="stylesheet" href="style.css">
     <script src="http://code.angularjs.org/1.2.7/angular.js"></script>
     <script>
       var app = angular.module('myApp', []);
       app.controller('MyCtrl', function($scope) {
          $scope.foo = function() { alert('foo'); }
          $scope.bar = function() { alert('bar'); }
       });

       app.directive('myAttr', function() {
        return {
          scope: true,
          link: function(scope, el, attrs) {  
             if(attrs.hasOwnProperty('ngClick')){
                scope.foo = function(){
                   scope.$parent.foo();
                   scope.$parent.bar();
                }  
             }
          }
        };
      });
     </script>
   </head>

    <body ng-controller="MyCtrl">
      <a my-attr ng-click="foo()" href="">click here!</a>
    </body>

   </html>

发生了什么事:

scope: true:默认情况下,指令不会创建新范围,只是共享其父范围。通过设置scope: true,该指令的每个实例都将创建一个子范围,它将原型继承父范围。

然后你可以简单地覆盖所需的方法(foo())和瞧

现场演示:

http://plnkr.co/edit/8A8y96wAhqGEowFaRQUH?p=preview

答案 3 :(得分:0)

我坦率地承认,我可能会完全误解你要做的事情。但是,考虑到您提供的示例,我认为通过更多地分离问题可能会更好。

从您的示例中可以看出,只要您的指令存在,您就会尝试一起触发foobar。如果foobar都是控制器的问题,那么为什么不将它们包装在另一个函数中并将该函数分配给元素的ng-click。如果foo是控制器的问题,但bar是指令的关注点,为什么不直接从指令代码触发bar功能?

如果假设“foo”“bar”中包含的功能由控制器创建者定义...

<!DOCTYPE html>
<html ng-app="myApp">
<head>
  <link rel="stylesheet" href="style.css">
  <script src="http://code.angularjs.org/1.2.7/angular.js"></script>
  <script>
    var app = angular.module('myApp', []);
    app.controller('MyCtrl', function($scope) {
      $scope.foo = function() { alert('foo'); }
      $scope.bar = function() { alert('bar'); }
      $scope.pak = function() {
        $scope.foo();
        $scope.bar();
      }
    });
  </script>
</head>
<body ng-controller="MyCtrl">
  <a ng-click="pak()" href="">click here!</a>
</body>
</html>

或者,如果“foo”中包含的功能假设由控制器创建者定义,但“bar”中包含的功能假定由指令创建者定义...

<!DOCTYPE html>
<html ng-app="myApp">
<head>
  <link rel="stylesheet" href="style.css">
  <script src="http://code.angularjs.org/1.2.7/angular.js"></script>
  <script>
    var app = angular.module('myApp', []);
    app.controller('MyCtrl', function($scope) {
      $scope.foo = function() { alert('foo'); }
    });
    app.directive('myAttr', function(){
      return {
        link: function(scope, element, attrs){
          element.click(function(){
            alert('bar');
          });
        }
      }
    });
  </script>
</head>
<body ng-controller="MyCtrl">
  <a ng-click="foo()" href="">click here!</a>
</body>
</html>