Search code examples
javascriptangularjsangularjs-directiverestangular

Creating an angular directive that binds a service?


Not sure if I am misunderstanding how directives are created here. Say for example I have a controller such as:

angular.module('myApp.controllers').controller('MyController', ['$scope', 'MyService', function($scope, MyService) {
    $scope.restangularService = MyService;
}

I then have a directive such as:

angular.module('myApp.directives').directive('myGrid', function() {
    return {
        restrict: 'A',
        templateUrl: 'some/path/here.html',
        scope: {
            restangularService: '&'
        },
        controller: ['$scope', function($scope) {
            //access $scope.restangularService to run some queries
        }
    };
});

I then use my directive as such:

<div data-my-grid data-restangular-service='restangularService'></div>

I would expect that in my directive I could access $scope.restangularService and make calls however it's not being populated correctly. Am I doing this totally wrong? Any input? I have a feeling I need to be using the ngModel directive somehow.


Solution

  • The "&" prefix of an isolate scope value in a directive provides "one-way binding" which makes available a getter function in the directive's scope.

    Any changes you make to the object will not make their way back up to the parent controller of the directive (it is "read-only"). So you can't access your 'restangularService' variable as you would in the controller's scope, without calling the getter function:

    angular.module('myApp.directives', []).directive('myGrid', function() {
        return {
            restrict: 'A',
            templateUrl: 'some/path/here.html',
            scope: {
                restangularService: '&'
            },
            controller: ['$scope', function($scope) {
                console.log($scope.restangularService()); // outputs service value
            }]
        };
    })
    

    Alternatively, you could use "=", which would allow you directly access the scope object you pass in:

    angular.module('myApp.directives', []).directive('myGrid', function() {
        return {
            restrict: 'A',
            templateUrl: 'some/path/here.html',
            scope: {
                restangularService: '='
            },
            controller: ['$scope', function($scope) {
                console.log($scope.restangularService); //outputs service value
            }]
        };
    })
    

    Plunk demonstrating both types