hopsey
hopsey

Reputation: 1513

AngularJS : Accessing particular directive scope from controller

I'm new to angular, so forgive me if I missed anything or misunderstand the docs.

I have a directive, which converts the element to 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 html element (it creates its dom inside element, including some div with label class - lets say it contains some string that should be dynamic, and should be translateable globally) and then I replace static jquery-generated label to interpolated one. I should be able to manage it from controller.

the problem is, that I can have many directives in one controller, let's 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 directive and jquery is run it would give something, like, let's say

<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 the controller, can I manage a particular directive? how to access the scope for a chosen one?

i assume that

// controller
$scope.label = "some content";

is going to change all of the labels

is there a way to achieve the goal? Or should I review the approach to the problem?

thanks in advance!

EDIT

I will also have dom elements, that would need to have directive attached from the controller level. they should also be maintainable from this level. so my idea is to provide a service, that would be some kind of facade with api, that would work on jquery-plugin'ed dom elements.

so lets say I would 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 no idea how to get changeLabel working...

Best usage of the facade would be from controller:

toBePlugined = $('div.tbp');

facade.createPlugin(toBePlugined, 'label');
facade.changeLabel(toBePlugined, 'label2');

why do I need a service for that? because I want to be able to amend pluginned elements configuration from various places in the script. that could include various divs, body tag, etc.

and now - my problem is to access the directive scope by provading its dom object reference. is it possible? I was trying to play with my-dir attribute on dom object with no effect.

Upvotes: 1

Views: 301

Answers (1)

PSL
PSL

Reputation: 123739

There could be multiple ways to solve this, here are a couple of ways. You could use isolated scoped directive (scope:{}) with 2-way (=), based on how you need it. You could also use scope:true, i.e creating a child scope from the directive (if using with ng-repeat you can even use it with no scope since it already creates a child scope). But this approach would be less reusable/flexible as compared to the directive with its own contract(isolate scoped).

So you could 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 from your controller, say you have a list of labels.

 $scope.labels = [{label:'label1'}, {label:'label2'}, {label:'label3'}]

then you could just do:

<div ng-repeat="item in labels" my-dir="item.label"></div>

Upvotes: 2

Related Questions