0
votes

What is the right way to access scope variables from a controller defined in a directive?

Example, I want to have the click event call a function on the parent directive's controller. In the parent directive, I want the controller to have access to the "constants", FOO_VIEW, BAR_VIEW, BAM_VIEW

Would it make more sense to put those constants in the top level controller, in this case SearchCtrl (not shown)?

Directives:

.directive('usersAndApps', function() {
        return {
            restrict:'EA',
            scope: true,
            controller: function() {
                this.toggleView = function(viewName){
                    console.log('show view ' + viewName);
                }
            },
            link:function(scope, elem, attrs) {
                scope.FOO_VIEW = 'fooView';
                scope.BAR_VIEW = 'barView';
                scope.BAM_VIEW = 'bamView';
            }
        }
    }).directive('usersAndAppsNav', function() {
        return {
            restrict: 'AE',
            require:'^?usersAndApps',
            replace:true,
            scope:true,
            link:function(scope,elem,attrs,usersAndAppsCtrl){
                scope.toggleView = function(viewName){
                    usersAndAppsCtrl.toggleView(viewName);
                }
            },
            templateUrl:'partials/usersAndApps/throwmeaway'
        }
    });

Template:

<div>
    <button class="btn btn-large btn-primary" ng-click="toggleView(FOO_VIEW)">Foo View</button>
    <button class="btn btn-large btn-primary" ng-click="toggleView(BAR_VIEW)">Bar View</button>
    <button class="btn btn-large btn-primary" ng-click="toggleView(BAM_VIEW)">Bam View</button>
</div>

Directive and nested (child) directive:

<div ng-controller="SearchCtrl">
    <users-and-apps>
        <users-and-apps-nav></users-and-apps-nav>
    </users-and-apps>
</div>
2

2 Answers

1
votes

What you have is fine, but since you are not using an isolate or transcluded scope in usersAndAppsNav, you don't need to define a controller API on usersAndApps — you can simply take advantage of prototypal scope inheritance to access method toggleViewParent if you define it on the scope associated with usersAndApps:

.directive('usersAndApps', function() {
return {
    restrict:'EA',
    scope: true,
    link:function(scope, elem, attrs) {
        scope.FOO_VIEW = 'fooView';
        ...
        scope.toggleViewParent = function(viewName){
            console.log('show view ' + viewName);
        }
    }
}
}).directive('usersAndAppsNav', function() {
return {
    restrict: 'AE',
    replace:true,
    scope:true,
    link:function(scope,elem,attrs) {
        scope.toggleView = function(viewName){
            scope.toggleViewParent(viewName);
        }
    },
   templateUrl: ...
}
});

Fiddle.

enter image description here

Note that you are already making use of prototypal inheritance when you write ng-click="toggleView(FOO_VIEW)" in your template — the only reason FOO_VIEW evaluates to fooView is because of prototypal inheritance — FOO_VIEW is defined on the scope associated with usersAndApps (scope 004), which the child scope (scope 005) finds via the inheritance chain/lookup (i.e., following the dashed line).

-3
votes

Take a look at this quick video tutorial that covers this topic @ http://www.egghead.io/video/LJmZaxuxlRc

He also has a bunch of other really great AngularJS tutorial videos linked off that site.