12

I have created a custom directive which has two values. first is config object and second is data object. I modify this config and data objects inside my directive which is reflecting it in parent scope. Which is causing me error when I have to use directive multiple times.

I followed https://umur.io/angularjs-directives-using-isolated-scope-with-attributes/ and I am using isolated scope.

I want one way data binding for objects in isolated scope. Whatever I change in directive function it should not reflect in the parent scope.

below is scope of directive.

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

here is how I access it in the link function of directive

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

I am assuming that pass by reference is happening here.

I am adding JSbin. check the console the value of object is changing and reflecting in parent scope.

https://jsbin.com/vagowe/edit?html,js,output

11
  • So what is the specific problem? Please show all relevant code and create a plunker demo that replicates issue Commented Oct 14, 2015 at 13:29
  • @charlietfl I have added the demo. hope you understand my problem Commented Oct 14, 2015 at 13:44
  • You have to use = two-way binding to pass objects to a directive. Commented Oct 14, 2015 at 13:45
  • @ThinkingMedia I am passing object to directive.. then I am modifying that object.. I dont want to reflect that object changes in parent scope... Two way data binding will reflect changes to parent scope. which I don't want. I want one way data binding of objects.. Commented Oct 14, 2015 at 13:47
  • 1
    var x = angular.copy($scope.config); Commented Oct 14, 2015 at 13:49

3 Answers 3

21
+50

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);
Sign up to request clarification or add additional context in comments.

5 Comments

great its working.. so we are passing object as stringifying object here and in directive parsing string to object right ?
true, instead of accessing as function(&) can access parent scope object (it two-way binding).
is this the proper and only way to solve this problem ?
I see this as better way, because there is no way to manipulate the parent scope object, if you use = or & there is always a chance of modifying the parent scope object
There is now a one-way binding as well scope: { config: '<' }
6

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);

2 Comments

I solved a la $scope.config = angular.copy($scope.config__); in my directive CONTROLLER. makes more sense I think and the copied array stays.
For a directive, I find angular.copy() makes more sense than angular.fromJson() for one way binding.
0

The simplest thing would be to use the below statement inside the directive/component-

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.