在指令中转换 ng-click [英] Transcluding ng-click in a directive

查看:21
本文介绍了在指令中转换 ng-click的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

(HTML)

<div ng-controller="Ctrl1"><h2>示例</h2><my-dir data-x="1"><button ng-click="refresh()" id="refresh1">刷新</button></my-dir><my-dir data-x="2"><button ng-click="refresh()" id="refresh2">刷新</button></my-dir>

(JavaScript)

var app = angular.module('someapp', []);app.controller('Ctrl1', function($scope){ });app.directive('myDir', function(){返回 {限制:'E',范围: {},模板:'<div><p>指令内容:</p><div ng-transclude></div></div>',转置:真实,链接:功能(范围,元素,属性){$scope.y = attrs.x+1;scope.refresh = function(){console.log("刷新调用, y = ", $scope.y);}}};});

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

额外说明:

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

解决方案

正如 dcodesmith 所指出的,嵌入的 ng-click 将绑定到控制器的范围而不是指令的范围.取决于您到底想要做什么,您可能希望这是行为(因为被嵌入的内容不是指令的一部分,为什么它应该调用指令范围的方法?).就个人而言,我会改为在控制器的范围内声明该方法.

app.controller('Ctrl1', function($scope){$scope.refresh = function() {console.log("刷新调用.");};});

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

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

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

//指令范围范围: {显示按钮:'='}

我使用这种方法遇到的最大问题是使用双向绑定"运算符 (=) 导致真"和假"被视为表达式.我只是不太喜欢那种感觉.

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

更新 2:

我创建了一个 plunkr 来展示我认为我将如何处理您的情况,尤其是在重复使用任何杂项控件时:

http://plnkr.co/edit/FhrSwcrSZScvCfhtCSjn

在本例中,两个按钮指令实际上是videoPlayer"指令的子代.它们的逻辑包含在该指令中,但它们是单独实例化的,并且不需要父指令运行.父指令"(视频播放器)只是公开 API 供孩子"使用.也不是父的方法是构造函数的方法,而不是作用域.我认为这很奇怪,但它完全取自 angular 文档:

http://docs.angularjs.org/guide/directive(关于页)

请注意,每个 videoPlayer 指令仍将具有自己的隔离范围.

I am building an AngularJS directive. I want that directive to wrap other contents which have an ng-click inside of it. The resulting button does not do anything when clicked. Here is a simplified version of the code which I tried:

(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);
            }
        }
    };
});

How can I change it so that the button actually triggers the $scope.refresh() function?

Extra clarification:

I need local object information for the directive (there can be multiple of this directive in the single controller), so I create a new scope.

解决方案

As dcodesmith points out, the transcluded ng-click will be bound to the controller's scope rather than the directive's. Depending on what exactly you want to do, you may wish for this to be the behavior (since the transcluded content is not part of the directive, why should it call a method of the directive's scope?). Personally, I would declare the method on the controller's scope instead.

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

In this case, your directive should declare the isolate scope, even if there is nothing in it.

Update: Based on your comment, why not just include the button in the directive template? In this case, it will already be associated with the correct scope.

If there are some situations that you will not need the refresh button, then expose that as an option through the directive as an attribute:

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

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

The biggest problem that I have with this approach is using the "two-way-binding" operator (=) to cause 'true' and 'false' to be treated as expressions. I just don't like the feel of that very much.

Anyway, hopefully this solves your problem... One more comment, and I'm saying this not even knowing if what you are implementing is actually a refresh button, but if it is, I would take a minute and consider whether you really need a "refresh" button. Angular excels at eliminating refresh button!

Update 2:

I've created a plunkr that shows how I think I would handle your situation, especially if any of the miscellaneous controls are reused:

http://plnkr.co/edit/FhrSwcrSZScvCfhtCSjn

In this example, the two button directives are effectively children of the "videoPlayer" directive. Their logic is contained within that directive, but they are instantiated separately, and not required for the parent directive to operate. The "parent directive" (videplayer) simply exposes the API for the "children" to use. Also not that the methods of the parent are methods of the constructor, not the scope. I think this is very strange, but it is taken exactly from the angular documentation:

http://docs.angularjs.org/guide/directive (last example on the page)

Note that each videoPlayer directive will still have it's own isolate scope.

这篇关于在指令中转换 ng-click的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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