在指令中转换ng-click

时间:2014-01-05 23:50:22

标签: javascript angularjs angularjs-directive

我正在构建一个AngularJS指令。我希望该指令包含其中包含ng-click的其他内容。单击时,生成的按钮不会执行任何操作。 这是我尝试的代码的简化版本:

(HTML)

<div ng-app="someapp">
    <div ng-controller="Ctrl1">
        <h2>Example</h2>
        <my-dir data-x="1">
            <button ng-click="refresh()" id="refresh1">Refresh</button>
        </my-dir>
        <my-dir data-x="2">
            <button ng-click="refresh()" id="refresh2">Refresh</button>
        </my-dir>
    </div>
</div>

(JavaScript的)

var app = angular.module('someapp', []);

app.controller('Ctrl1', function($scope){ });

app.directive('myDir', function(){
    return {
        restrict: 'E',
        scope: {},
        template: '<div><p>Directive contents:</p><div ng-transclude></div></div>',
        transclude: true,
        link: function(scope, element, attrs){
            $scope.y = attrs.x+1;
            scope.refresh = function(){
                console.log("Refresh Called, y = ", $scope.y);
            }
        }
    };
});

如何更改它以便按钮实际触发$ scope.refresh()函数?

额外澄清:

我需要指令的本地对象信息(单个控制器中可能有多个指令),所以我创建了一个新的范围。

2 个答案:

答案 0 :(得分:2)

正如dcodesmith指出的那样,转换的ng-click将绑定到控制器的范围而不是指令的范围。根据您想要做什么,您可能希望这是行为(因为被转换的内容不是指令的一部分,为什么它应该调用指令范围的方法?)。就个人而言,我会在控制器的范围内声明该方法。

app.controller('Ctrl1', function($scope){ 
    $scope.refresh = function() {
        console.log("Refresh called.");
    };
});

在这种情况下,您的指令应该声明隔离范围,即使其中没​​有任何内容。

更新:根据您的评论,为什么不在指令模板中包含该按钮?在这种情况下,它已经与正确的范围相关联。

如果在某些情况下你不需要刷新按钮,那么通过指令将其作为选项公开为属性:

<my-dir show-button='true'></my-dir>

// directive scope
scope: {
    showButton: '='
} 

我使用这种方法遇到的最大问题是使用“双向绑定”运算符(=)将'true'和'false'视为表达式。我只是不喜欢那种感觉。

无论如何,希望这能解决你的问题...... 还有一个评论,我说这甚至不知道你实现的是否实际上是一个刷新按钮,但如果是,我会花一点时间考虑你是否真的需要一个“刷新”按钮。 Angular擅长消除刷新按钮!

更新2:

我创建了一个plunkr,显示我认为我会如何处理你的情况,特别是如果重用任何其他控件:

http://plnkr.co/edit/FhrSwcrSZScvCfhtCSjn

在此示例中,两个按钮指令实际上是“videoPlayer”指令的子代。它们的逻辑包含在该指令中,但它们是单独实例化的,并且父指令不需要操作。 “父指令”(videplayer)简单地公开了要使用的“孩子”的API。也不是父类的方法是构造函数的方法,而不是范围。我认为这很奇怪,但它完全取自角度文档:

http://docs.angularjs.org/guide/directive(页面上的最后一个示例)

请注意,每个videoPlayer指令仍然拥有自己的隔离范围。

答案 1 :(得分:0)

删除scope对象。那里似乎发生了冲突。

摘自Creating a Directive that Wraps Other Elements

  

transclude选项会更改范围嵌套的方式。它使得transcluded指令的内容具有指令之外的任何范围,而不是内部的任何范围。这样做,它使内容访问外部范围。

app.directive('myDir', function(){
    return {
        restrict: 'E',
        //scope: {}, remove this line.
        template: '<div><p>Directive contents:</p><div ng-transclude></div></div>',
        transclude: true,
        link: function(scope, element, attrs){
            console.log("X-attr", attrs.x);
            scope.refresh = function(){
                console.log("Refresh Called");
            }
        }
    };
});