When using isolate scope (scope: {}
) in AngularJS directives, you might face binding issues, such as:
- Directive not updating when parent scope changes.
- Two-way (
=
) binding not reflecting changes properly. - One-way (
@
) binding not receiving values correctly. - Functions in
&
binding not executing as expected.
1. Understanding Isolate Scope in Directives
When we define scope: {}
in a directive, it creates a separate scope from the parent controller.
Example of Isolate Scope with Different Bindings
app.directive("customBox", function() {
return {
restrict: "E",
scope: {
title: "@", // One-way string binding
count: "=", // Two-way binding
onClick: "&" // Function binding
},
template: `<div class="box">
<h3>{{ title }}</h3>
<p>Count: {{ count }}</p>
<button ng-click="onClick()">Click Me</button>
</div>`
};
});
This directive accepts:
@
→ One-way string binding.=
→ Two-way data binding.&
→ Parent function binding.
Usage in HTML
<div ng-controller="MainCtrl">
<custom-box title="Hello" count="num" on-click="increment()"></custom-box>
</div>
app.controller("MainCtrl", function($scope) {
$scope.num = 5;
$scope.increment = function() {
$scope.num++;
};
});
Expected Behavior:
title="Hello"
should show"Hello"
in the directive.count="num"
should reflect$scope.num
.- Clicking “Click Me” should call
increment()
and increasenum
.
2. Common Binding Issues & Fixes
Issue 1: Two-Way Binding (=
) Not Updating
If the parent scope updates the value, but the directive does not reflect changes, the issue is likely scope synchronization.
Problem Example
app.directive("customBox", function() {
return {
restrict: "E",
scope: { count: "=" },
template: `<p>Count: {{ count }}</p>`
};
});
<custom-box count="num"></custom-box>
<button ng-click="num = num + 1">Increase</button>
Problem: Clicking the Increase button does not update count
inside the directive.
Solution: Use $watch()
for Synchronization
app.directive("customBox", function() {
return {
restrict: "E",
scope: { count: "=" },
template: `<p>Count: {{ count }}</p>`,
link: function(scope) {
scope.$watch("count", function(newVal) {
console.log("Count updated:", newVal);
});
}
};
});
Now, count
will update properly when changed from the parent scope.
Issue 2: One-Way (@
) Binding Not Working
If an attribute binding (@
) is not receiving values, the issue is usually missing interpolation ({{}}
).
Problem Example
<custom-box title=Hello></custom-box> <!-- Incorrect -->
Problem: title
is treated as a literal string instead of "Hello"
.
Solution: Use Quotes (""
) for String Attributes
<custom-box title="Hello"></custom-box> <!-- Correct -->
Now, title
will correctly receive "Hello"
in the directive.
Issue 3: Parent Function (&
) Not Executing
If a function binding (&
) is not working, it’s usually due to missing parameters or incorrect execution.
Problem Example
<custom-box on-click="increment()"></custom-box>
app.directive("customBox", function() {
return {
restrict: "E",
scope: { onClick: "&" },
template: `<button ng-click="onClick()">Click</button>`
};
});
Problem: Clicking the button does nothing.
Solution: Ensure Correct Function Execution
template: `<button ng-click="onClick({ value: 10 })">Click</button>`
Pass parameters correctly when calling parent functions.
Issue 4: Directive Losing Parent Scope Values
If a directive is inside an ng-repeat
and the values disappear, it may be due to scope conflicts.
Problem Example
<div ng-repeat="item in items">
<custom-box count="item.count"></custom-box>
</div>
Problem: item.count
inside ng-repeat
does not update inside the directive.
Solution: Use track by
<div ng-repeat="item in items track by $index">
<custom-box count="item.count"></custom-box>
</div>
Fixes scope conflict issues inside ng-repeat
.