Utilizing AngularJS isolated scope is an effective method for creating reusable components within angular directives. I find it to be quite beneficial. There are occasions when access to child scopes is necessary for data manipulation or method invocation. Angular provides two options for achieving this:
(1) Utilizing isolated scope with attribute bindings, as shown below:
scope: {
someObject: '='
},
(2) Accessing the child scope through DOM element's scope().$$childHead. The reliability of $$childHead as a direct reference to the child scope is not always guaranteed according to the Angular official documentation.
scope().$$childHead
The first option presents a limitation in that it only allows interaction with the bound object/data and does not grant full access to the scope itself. While this may align with Angular's design philosophy, I desired complete access to the isolated scope along with its isolation feature. To address this need, I developed the following code snippet (utilizing new LinkControl(function(scope, element, attr)){...}):
function LinkController(callback){
var self = this;
self.callback = callback;
return function(scope, element, attr){
LinkController._retainScope(scope, element, attr);
self.callback.apply(this, arguments);
}
}
LinkController._scopes = {};
LinkController.get = function(scopeId) {
return LinkController._scopes[scopeId];
};
LinkController._retainScope = function(scope, element, attr){
if (typeof(attr) === 'undefined') return;
if (typeof(attr.scopeId) === 'undefined') return;
var scopeId = attr.scopeId;
LinkController._scopes[scopeId] = {
scope: scope,
element: element,
attr: attr
};
if (typeof(element) != 'undefined') {
element.on('$destroy', function(){ LinkController._releaseScope(scopeId); });
}
};
LinkController._releaseScope = function(scopeId){
delete LinkController._scopes[scopeId];
};
Usage Examples:
Parent Controller
app.controller('MainController', ['$scope', function($scope){
var parentData = [1, 2, 3, 4];
var anotherValue1 = LinkController.get('td01').attr.anotherValue || 'default value';
var anotherValue3 = LinkController.get('td03').attr.anotherValue || 'default value';
LinkController.get('td01').scope.data = parentData;
LinkController.get('td02').scope.showNext();
LinkController.get('td03').element.css({opacity: '.5'});
}]);
HTML
<test-directive scope-id="td01" any-attr="hello world" />
<test-directive scope-id="td02" any-attr="foo bar" />
<test-directive scope-id="td03" any-attr="alibaba" another-value="test value" />
Directive
app.directive('testDirective', function(){
return {
restrict: 'EA',
scope: {},
link: new LinkController(function(scope, element, attr){
scope.data = {};
scope.showNext = function(){};
scope.showPrevious = function(){};
})
};
});
This implementation ensures memory safety by appropriately releasing scope pointers.
I welcome your candid feedback or suggestions for improving this approach.