Angularjs directives isolated scope + one-way data-binding not working for objects?

passing text is one-way binding(@) and passing object is two-way binding(=)

passing object as text

<custom-directive config="{{config}}"></custom-directive>

scope in directive

scope: {
  config: "@"
}

converting the string back to object in link

var config = angular.fromJson(scope.config);

You are correct, the issue is that your JavaScript objects are being passed by reference. Using a one-way binding copies the reference, but the reference will still point to the same object.

My impression from the Angular docs for directives has always been:

  • The '@' binding is intended for interpolated strings
  • The '=' binding is intended for structured data that should be shared between scopes
  • The '&' binding is intended for repeatedly executing an expression that is bound to the parent scope

If you want to treat the bound object from the parent as immutable, you can create a deep copy the objects inside your link code using angular.copy:

var config = angular.copy(scope.config());
var dataObj = angular.copy(scope.dataObj());

Alternatively, you can use a two-way binding for this and copy the object in the same way:

scope: {
    config: "=",
    dataObj: "="
}

// ...
// Inside the link function of the directive.
// Note that scope.config and scope.dataObj are no longer functions!

var config = angular.copy(scope.config);
var dataObj = angular.copy(scope.dataObj);