alexg
alexg

Reputation: 922

Obtain access to a controller from a child directive in AngularJS

I have a small angular application that needs to list a list of entities (endpoints in my case). The entities are saved in an array. For the purpose of this example, let's say they're on the controller.

To better separate the logic, I created two directives: endpointList and endpoint, like this:

the directives are declared like this:

 myApp.directive('endpointList', function () {
        return {
            restrict:'EA',
            controller:'EndpointCtrl',
            controllerAs:'epCtrl',
            transclude: true,
            replace: true,
            templateUrl: 'endpoint-list.html'
        };
    })
    .directive('endpoint', function ($compile, $log) {
        return {
            scope: {
                scope:'=ngModel',
                func:'&',
                index:'@'
            },
            restrict:'EA',
            replace:true,
            templateUrl: 'endpoint.html',
            require:'?^endpointList',
            compile: function(tElem, tAtt) {
                return function(scope, el, attr, ctrl) {
                    // ctrl.addResource(scope);
                }
            }
        };
    });

the template for endpoint-list.html

...
<section>
    <table class="table table-hover">
        <thead>
            <tr>
                <th><input type="checkbox" ng-model="selectAll" ng-click="toggleSelectAll()"/></th>
                <th>Label</th>
                <th>Last updated</th>
                <th>Status</th>
                <th>Sync</th>
            </tr>
        </thead>
        <tbody ng-transclude></tbody>
    </table>
</section>
...

the template for endpoint.html:

...
<td>
    <a ng-click="sync()" class="glyphicon glyphicon-cloud">CALL ME</a>
</td>
...

and I use them like this:

<endpoint-list>
    <endpoint ng-repeat="ep in endpoints" scope="ep" ng-model="ep" func="selectEp(scope)" index="{{$index}}"></end-point>
</endpoint-list>

My problem is that in the endpoint.html I have a link that, when clicked, I want it to call the function sync() on the controller:

$scope.sync = function(endpoint) {
    console.log('syncing:');
    console.log(endpoint);
};

How can I do that? Any tips are greatly appreciated.

Here's the plunkr: http://plnkr.co/edit/js7syyZ8u0i9KoOIgwdQ

Upvotes: 1

Views: 48

Answers (1)

Manish Kr. Shukla
Manish Kr. Shukla

Reputation: 4477

You can create a service as a middle man, inject it in both your controller and directive, and that's it. You'll be able to call that service's method directly from your directive's template, provided that your controller has a reference to your service.

myApp.service("middleManService", function() {
    this.sync = function(endpoint) {
        console.log('syncing:');
        console.log(endpoint);
    };

        this.test = 'blah';

        this.selectAll = false;
        this.deleteBtnVisible = false;
        this.editBtnVisible = false;

        this.endpoints = [
            {
                label: '2.2.0',
                url: 'https://version-2_2_0-api.company.com/test/test?api_key=xxx',
                selected: false
            },
            {
                label: '2.3.0',
                url: 'https://version-2_3_0-api.company.com/test/test?api_key=xxx',
                selected: false
            }
        ];
    };
});

Add the reference to this service to your controller :

 myApp.controller('EndpointCtrl',    
    function ($scope, middleManService) {
        $scope.middleManService = middleManService;

And then in your html, call it like this :

    <td>
        <a ng-click="middleManService.sync()" class="glyphicon glyphicon-cloud">CALL ME</a>
    </td>

Upvotes: 1

Related Questions