Itamar L.
Itamar L.

Reputation: 519

One time binding not working inside custom AngularJS Directive

I'm trying to wrap my head around the reason that the one-time bound value (obj.value) inside the directive in this code example is being updated?

Updating the first field will update the bound value inside the directive only once, as expected. Afterwards, inside the directive, when clicking "edit", it will also update the one-time bound value AND also update the parent scope. Updating the first field again will not change the value inside the directive.

<html>
<head>
     <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
</head>
<body ng-app="myApp" ng-controller="myCtrl" ng-model-options="{updateOn: 'blur'}">
  Enter value here first, then press edit:<br>
    <input type="text" ng-model="t.value"><br>
    <br>
    Press edit, change the value and press copy:
    <my-directive obj="t"></my-directive><br><br>

    <script>

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

    myApp.directive('myDirective', function() {
        var directive = {};

        directive.restrict = 'E';
        directive.template = '<div ng-switch="edit">\
                                <div ng-switch-default>[{{ ::obj.value }}]<button ng-click="toggle()">edit</button></div>\
                                <div ng-switch-when="true">\
                                    <input type="text" ng-model="clone.value">\
                                    <button ng-click="copy()">copy</button>\
                                </div>\
                            </div>';
        directive.scope = {
            obj: '='
        };

        directive.controller = function($scope) {
            $scope.edit = false;

            $scope.toggle = function() {
                $scope.edit = true;
                $scope.clone = angular.copy($scope.obj);
            }

            $scope.copy = function() {
                $scope.obj = angular.copy($scope.clone);
                $scope.edit = false;
            }
        }

        return directive;
    });

    myApp.controller('myCtrl', function(){

    });

    </script>
</body>

http://plnkr.co/edit/tbC3Ji6122gdqt4XbZpI?p=preview

Upvotes: 1

Views: 937

Answers (2)

Sander_P
Sander_P

Reputation: 1835

It is because of ng-switch. Every time it's expression is recalculated the directive is 'redrawn'. And every time is does that the one time expression is also recalculated.

If you change your template to:

directive.template = '{{::obj | json}}<div ng-switch="edit">
etc...

you will see it won't change because it is outside of the ng-switch.

Upvotes: 0

mpaarating
mpaarating

Reputation: 53

In 1.3 they added a new syntax for helping with one-way binding, "::". So you just need to change your directive implementation to obj="::t".

Here's an update to your plnkr: http://plnkr.co/edit/7lsiX1ItPiQoVpJcQ6iW?p=preview

Here's a nice article that explains a bit more

Upvotes: 1

Related Questions