AngularJS: accessing a specific scope of a directive from a controller
I am new to angular so forgive me if I missed anything or misunderstood the docs.
I have a directive that converts an element to a jquery plugin
.directive('myDir', function($compile) {
return {
link: function(scope, element, attributes) {
// $('.someDiv').jqueryPlugin(...);
element.jqueryPlugin();
var el = $compile("<span translate>{{ 'label' }}</span>")(scope);
element.find('.label').html(el);
}
}
})
as you can see, first I create a jquery plugin in an html element (it creates its inner element inside, including some div with a label class - lets say it contains some string that should be dynamic and should be globally translatable) and then I replace the old jquery-generated label with an interpolated one. I need to be able to control it from the controller.
the problem is that i can have many directives in one controller, say
<div my-dir class="label-inside-1"></div>
<div my-dir class="label-inside-2"></div>
<div my-dir class="label-inside-3"></div>
<div my-dir class="label-inside-4"></div>
after the directive is run and jquery it will give something like let
<div my-dir class="label-inside-1">
<div class="label">
<span>{{label|translate}}</span>
</div>
</div>
<div my-dir class="label-inside-2">
<div class="label">
<span>{{label|translate}}</span>
</div>
</div>
<div my-dir class="label-inside-3">
<div class="label">
<span>{{label|translate}}</span>
</div>
</div>
<div my-dir class="label-inside-4">
<div class="label">
<span>{{label|translate}}</span>
</div>
</div>
how, from a controller, can i control a specific directive? how to access the area for the selected one?
i suppose that
// controller
$scope.label = "some content";
going to change all labels
Is there a way to achieve the goal? Or should I consider approaching the problem?
early!
EDIT
I will also have dom elements that need to have a directive attached from the controller level. they must also be supported from this level. so my idea is to provide a service that will be some kind of facade with an api that will work with the jQuery-plugin 'house elements.
so let's say I need something
.provider('facade', function() {
this.$get = function($rootScope, $compile) {
return {
createPlugin: function(domElement, defaultLabel) {
domElement.attr('my-dir', defaultLabel);
$compile(domElement)($rootScope);
},
changeLabel(domElement, newLabel) {
// get a scope of myDir for provided dom element
scope.label = newLabel;
}
}
};
})
it works for createPlugin but dont know how to get changeLabel to work ...
The best use of the facade would be from the controller:
toBePlugined = $('div.tbp');
facade.createPlugin(toBePlugined, 'label');
facade.changeLabel(toBePlugined, 'label2');
why do i need a service? because I want to be able to change the configuration of the plugin items from different places in the script. which can include various divs, body tags, etc.
and now - my problem is accessing the scope of the directive by checking its reference to the dom object. Is it possible? I was trying to play with my-dir attribute on a dom object with no effect.
source to share
There may be several ways to solve this problem, here are several ways. You can use the dedicated bounded directive ( scope:{}
) with two-way ( =
), based on how you need it. You can also use scope:true
, i.e. Create child scope from directive (if you are using with ng-repeat, you can even use it without scope as it already creates child scope). But this approach would be less reusable / flexible compared to the directive with its own contract (isolate scope).
So you can change your directive to:
.directive('myDir', function($compile) {
return {
scope:{
label:'=myDir' //Set up 2 way binding
},
link: function(scope, element, attributes) {
// $('.someDiv').jqueryPlugin(...);
element.jqueryPlugin();
var el = $compile("<span translate>{{ 'label' }}</span>")(scope);
element.find('.label').html(el);
}
}
});
and bind to your controller, let's say you have a list of labels.
$scope.labels = [{label:'label1'}, {label:'label2'}, {label:'label3'}]
then you can simply do:
<div ng-repeat="item in labels" my-dir="item.label"></div>
source to share