具有隔离范围的AngularJS指令 - 我真的必须在任何地方调用$ parent吗?

FMM*_*FMM 3 javascript angularjs

我有一个angular.js指令来创建一个按钮(悬停类,左右图标等).我正在使用按钮的左右图标的自动绑定,scope: { uiButtonIconLeft: '@', uiButtonIconRight: '@' }以便我可以将这些值绑定到父作用域的数据.但是,这会导致angularjs创建一个"隔离"范围,这意味着在这种情况下使用我的指令不起作用:

<div ng-controller='someController'>
    <a ng-repeat='thing in things'
       ui-button
       ui-button-icon-left='{{thing.icon}}'
       ng-click='someMethodTheControllerPutOnTheScope(thing.id)'
       >
       I don't work, don't bother clicking me
    </a>
</div>
Run Code Online (Sandbox Code Playgroud)

我必须这样做:

<div ng-controller='someController'>
    <a ng-repeat='thing in things'
       ui-button
       ui-button-icon-left='{{thing.icon}}'
       ng-click='$parent.someMethodTheControllerPutOnTheScope($parent.thing.id)'
       >
       Holy leaky abstractions, Batman, it works!
    </a>
</div>
Run Code Online (Sandbox Code Playgroud)

我的问题是:这是惯用的吗?应该这样吗?我做错了吗?我们的英雄可以$parent.<whatever>在他的标记中清除多余的,重复的,恼人的额外内容吗?

编辑

我为我的按钮"小部件"确定的答案是避免使用隔离范围并通过范围观察左右图标的属性值attributes.$observe(...)而不是绑定.

Umu*_*acı 10

有一种方法可以在不使用显式范围的情况下完成它,如果您正在编写一个不专门处理范围内元素的指令,那么最好这样做:

function MyDirective () {
    return {
        link: function (scope, iElement, iAttrs) {
            iAttrs.$observe("uiButtonLeft", function (val) {
                if (val) {
                    iElement.attr(src, val); // whatever you want to do
                }
            });
        }

}
Run Code Online (Sandbox Code Playgroud)

.

<img ui-button ui-button-left="{{item.leftBtn}}"></img>
Run Code Online (Sandbox Code Playgroud)

有时使用{{val}}变得麻烦,要么是干净的代码,要么你也可能想要改变val.这是你如何做到的.

function MyDirective () {
    return {
        link: function (scope, iElement, iAttrs) {
            iAttrs.$observe("uiButtonLeft", function (val) {
                scope.$watch(val, function (valInScope) {
                    if (valInScope) {
                        iElement.attr(src, valInScope); // whatever you want to do

                        // the following statement updates the value in scope
                        // it's kinda weird, but it works.
                        scope.$apply(val + "= Hello"); // if you are out of angularjs, like jquery event
                        scope.$eval(val + = "Hello"); // if you are in angualrjs
                        // $apply can handle string, it's like ngClick
                        // you use in templates. It updates the value correctly.
                    }
                }
            });
        }

}
Run Code Online (Sandbox Code Playgroud)

.

<img ui-button ui-button-left="item.leftBtn"></img>
Run Code Online (Sandbox Code Playgroud)


Ben*_*lda 5

@仅适用于本地范围属性.&相反,尝试允许您在父作用域的上下文中执行表达式.

引自http://docs.angularjs.org/guide/directive

&&attr- 提供在父作用域的上下文中执行表达式的方法.如果未指定attr名称,则假定属性名称与本地名称相同.给定<widget my-attr="count = count + value">范围的给定和窗口小部件:{ localFn:'&myAttr' },然后隔离范围属性localFn将指向count = count + value表达式的函数包装器.通常需要通过表达式将数据从隔离范围传递到父范围,这可以通过将局部变量名称和值的映射传递到表达式包装器fn来完成.例如,如果表达式是,increment(amount)那么我们可以amount 通过调用localFnas 来指定值localFn({amount: 22})

John Lindquist在他的网站egghead.io视频的17,18和19 上报道了这一点.