iurii
iurii

Reputation: 4230

How does '=' operator works in angular directive isolated scope with 'true' and 'false' values?

I had some code in angular v1.2 that worked.

<some-directive isFull="false"></some-directive>

.directive('someDirective', [function() {
    return {
        restrict: 'E',
        scope: {
            isFull: '@'
        },
        template: '<h1 ng-if="isFull">Test Template</h1>'
    };
}])

isFull was set to falsy js value in template.

After migrating to angular v1.4 this logic breaks because as I see https://github.com/angular/angular.js/commit/bdfc9c02d021e08babfbc966a007c71b4946d69d false is interpreted as a string and now it is a true js value.

So I changed

scope: {
    isFull: '='
},

and this does the trick. But according to the doc, with '=' we do a binding to the parent scope.

Can someone please explain how '=' works with 'true' and 'false' boolean values?

Upvotes: 1

Views: 1002

Answers (2)

DonJuwe
DonJuwe

Reputation: 4563

I think the docs may explain it better than I can:

  • @ or @attr - bind a local scope property to the value of DOM attribute. The result is always a string since DOM attributes are strings. If no attr name is specified then the attribute name is assumed to be the same as the local name. Given <widget my-attr="hello {{name}}"> and widget definition of scope: { localName:'@myAttr' }, then widget scope property localName will reflect the interpolated value of hello {{name}}. As the name attribute changes so will the localName property on the widget scope. The name is read from the parent scope (not component scope).
  • = or =attr - set up bi-directional binding between a local scope property and the parent scope property of name defined via the value of the attr attribute. If no attr name is specified then the attribute name is assumed to be the same as the local name. Given <widget my-attr="parentModel"> and widget definition of scope: { localModel:'=myAttr' }, then widget scope property localModel will reflect the value of parentModel on the parent scope. Any changes to parentModel will be reflected in localModel and any changes in localModel will reflect in parentModel. If the parent scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You can avoid this behavior using =? or =?attr in order to flag the property as optional. If you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use =* or =*attr (=*? or =*?attr if the property is optional).

Upvotes: 1

Sulthan
Sulthan

Reputation: 130122

= is two-way binding, it is usually used with a variable:

<some-directive is-full="myVar"></some-directive>

.directive('someDirective', [function() {
    return {
        scope: {
            isFull: '='
        }
    };
}]);

This means that when you change myVar in the parent scope, the value of isFull will change in the directive to the value of myVar. And viceversa, if you change the value of isFull in the directive, it will get propagated to myVar.

Your case is a bit special because you don't have two variables but you have an angular expression which will get evaluated first. Then it will work exactly the same.

You could actually use the new one-time binding is-full=":: false" because this value won't ever change.

There is nothing special about booleans here.

Upvotes: 1

Related Questions