deitch
deitch

Reputation: 14581

Can an angular directive contain a controller?

Or perhaps a better question is, should a directive contain a controller?

For reasons of separation, my index.html is a simple file. Everything is rendered into it via templates. So my index.html is real simple:

<body ng-app="myapp"><mainmenu></mainmenu><div ng-view></div></body>

I don't really need a directive for mainmenu, but it allows me to put the menu in a separate template file. The main menu itself contains user info, login/logout, and a search box.

    <div class="leftmenu" ng-show="isLogin()">
    <ul class="menu"> 
        <li><a href="/part1">Part1</a></li> 
        <li><a href="/part2">Part2</a></li> 
        <li><a href="/part3">Part3</a></li> 
    </ul>

    <div ng-controller="Search" class="Search><input type="text" ui-select2="s2opts" style="width:250px;" ng-model="search" data-placeholder="search"></input></div>
</div>

<div class="rightmenu">
    <ul ng-show="isLogin()" class="menu">
        <li><a href="/account">My Account</a></li>
        <li><a href="/logout" ng-click="logout()">Logout</a></li>
    </ul>
    <ul ng-show="!isLogin()" class="menu">
        <li><a href="/login">Login</a></li>
        <li><a href="/register">Register</a></li>
    </ul>
</div>

So there is the menu part, with its own controller, and the search, with its own, embedded between the two parts.

Of course, my mainmenu directive unit tests fail because SearchController isn't defined. But this leaves me wondering if I am going about this wrong. Should I even have it like this, a section of html with an explicit ng-controller defined inside it? Doesn't this create all sorts of weird dependencies?

How should I better structure this? A search directive that is included so I can unit test it separately? Something feels wrong here structurally...

UPDATE:

As requested, a basic fiddle: http://jsfiddle.net/nj4n44zx/1/

Upvotes: 0

Views: 379

Answers (3)

benek
benek

Reputation: 2178

As specified by the Angular documentation, the best practice is to define a controller inside a directive only to expose an API to another directive. Otherwise the link function is sufficient.

See at the bottom of :

Angular directives

By experience using controllers inside a directives shadow what you are doing in your scope. It does not help to have a easy readable code.

I do prefer using the main controller where the directive is included. With a non isolated scope you have access to everything from the link function.

Upvotes: 1

Mathieu Bertin
Mathieu Bertin

Reputation: 1624

sure your directive can contain a controller because you declare a directive like this

myApp.directive('mainMenu', function() {
    return {
        restrict: 'E',
        replace: true,
        scope: true,
        templateUrl: 'menu.html',
        controller:['$scope', function($scope) {
            //define your controller here
        }]
    };
});

Upvotes: 0

Jarema
Jarema

Reputation: 3586

I usually deal with it like that:

app.directive('topMenu', function() {
    return {
        restrict: 'E', // or whatever You need
        templateUrl: '/partials/topmenu', //url to Your template file
        controller: function($scope) {
            $scope.foo = "bar";
        }
    };
});

Then, in that template You don't have to add ng-controller.

Upvotes: 0

Related Questions