Correct use of & bindings in directives

This got me in the answers and sparked some discussion and I would like if I'm leaving the base or if there is a "more angular" way to achieve my goal.

When I write a directive that will use isolated scope, the question that comes up is always =, and or @.

Typically, people always think of and as a way to pass functions to a directive. The documentation describes it as:

the way the expression is executed in the context of the parent scope. If attr is not specified, the attribute name is assumed to be the same as the local name. Defined and visible scope definition: {localFn: '& myAttr'}, then isolating the scope property localFn will point to the function wrapper for the expression count = count + value. It is often desirable to transfer data from the enclosed space via an expression to the parent scope, this can be done by going through a map of local variable names and values ​​into the fn expression wrapper. For example, if the expression is an increment (amount), then we can specify the amount value by calling localFn as localFn ({amount: 22}).

I use it to pass functions quite a bit, but I also use it in cases where I want to pass an expression that returns a non-string, and I don't want my directive to be able to change the values ​​in the parent scope. In other words, I use it like:

a way to execute the expression in the context of the parent scope

So, if I don't need two-way binding, and the expression is not a string, I'll do this:

.directive('displayObject', function() {

    scope: {
        value: '&=displayObject'
    },
    template: '<div ng-repeat="(k, v) in value()">{{k}}: {{v}}</div>',
    replace: true,
    ...
});

      

Using the directive would be:

<div displayObject="someScopePropertyOrExpression"></div>

      

= is not ideal here because I don't need two-way binding. I don't want my directive to change the value in the parent field, and I don't want the clock to support it.

@ is not ideal because it interpolates the attribute, so the value will always be a string.

:: someScopePropertyOrExpression doesn't work because I want the directive pattern to reflect changes in someScopePropertyOrExpression if it changes.

In every discussion, it always came up that

ng-repeat="(key, value) in value()"

      

sets the clock - the problem is that = and the template together set two - one, which is completely unnecessary.

Several times when I suggested this pattern, it was called "hack" or misuse of &, and even "ugly".

I don't think this is any of them, but if so, then my specific question is what is the alternative?

+2


source to share


1 answer


I searched quite a bit to prove you are wrong in our discussion here , but I think you are correct - this is the only way to create one -way (from parent to isolate scope) bindings to the real model.

In this aspect it is "&"

superior "="

because, as you noted, it "="

sets the clock in the parent area when it "&"

doesn't.

One thing - plunker 1 - (which I finally managed to uncover) that hints that this is a hack is that it doesn't play nice with Angular's one-time binding foo="::name"

:

"="

will honor a one-time binding (it sets the clock for the parent and removes it before the next digest), whereas it "&"

won't:



<input ng-model="name">
<div two-way="::name">
<div one-way="::name">

      

The other - plunker 2 is what "&"

allows local variables to be passed and they can modify external variables:

<input ng-model="name">
<div one-way="name">

      

But in the directive, if you did something like:, "{{oneWay({name: 'fooo'})}}"

this will make it display "fooo"

rather than take a value name

from the outer scope. It's a bit like shooting in the foot, yes, but it hints that this use may be slightly different from the original intent.

0


source







All Articles