32

Is it possible to apply multiple AngularJS controllers on the same element ?

2
  • 3
    You can nest the second controller at the first and call then as one. Or you could make a third file that is composed by the other two. This answer is from groups.google.com/forum/#!topic/angular/r294h-v2Iys - Hoskins, Jim Commented Feb 20, 2015 at 21:53
  • 1
    @klauskpm, sometimes it is necessary. For example, let's say you have a controllers hierarchy (A -> B -> C) nested. The info you want to set on the page's <title> is in controller C. Where do you put that controller? Of course, there is <html>, there is <head> and there is the <title>, but you may not want to instantiate another instance of a controller just for this purposes, as it may be expensive. Commented Sep 24, 2015 at 2:56

5 Answers 5

35

No, you cannot apply two controllers to the same element, but you can apply multiple directives. And directives can have controllers.

app.directive('myDirective1', function() {
return {
controller: function(scope) {
  //directive controller
  }
 };
});

app.directive('myDirective2', function() {
return {
controller: function(scope) {
  //directive controller
  }
 };
});

and in the HTML:

<div myDirective1 myDirective2></div>

And as mentioned in the comments below, the two controllers could share the same scope, which is often the desired effect; one of the two controller can request a new scope, but you cannot have two new scopes;

the reason for not allowing two isolated scope on the two directives, is that the view would not know where to get the scope values from, if a scope variable had the same name in the two isolated directive controllers

Here is an interesting read: Why can't multiple directives ask for an isolated scope on the same element?

Sign up to request clarification or add additional context in comments.

4 Comments

This however doesn't actually create multiple controllers. See stackoverflow.com/questions/19352649/… "If multiple directives on the same element request a new scope, only one new scope is created"
The two controllers could share the same scope, which is often the desired effect; one of the two controller can request a new scope, but you cannot have two new scopes;
@Manube relative to the reasons for not allowing it, wouldn't it happen when you have nested controllers?
@Drumnbassn nested controllers share $scope via prototypal inheritance; see jimhoskins.com/2012/12/14/nested-scopes-in-angularjs.html so I believe there is no dilemna in that case; as opposed to two isolated scopes applying to the same element (which angularjs will not allow, to avoid erratic behaviour: only one directive per element can have an isolated scope)
32

You could extend a controller and use it wherever you like. See the Fiddle for a better example.

<script>
var multiApp = angular.module('new', []);

multiApp.controller('aCtrl', ['$scope', '$controller', function ($scope, $controller) {
  $scope.text1 = 'Hello';

  angular.extend(this, $controller('bCtrl', {$scope: $scope}));
}]);



multiApp.controller('bCtrl', ['$scope', function ($scope) {
                $scope.text2 = 'World!';
}]);
</script>

With html like:

<body ng-app="new">
    <div id="container1" ng-controller="aCtrl">
        {{text1}} {{text2}}
    </div>
</body>

Fiddle: http://jsfiddle.net/kkelly/thk9n20o/#base.com

1 Comment

I found this quite useful as it basically allows multiple controlers on the same element. My purpose was simply to break up the controllers for organization while sharing the scope and this was perfect for that.
8

No

HTML is a form of XML, and it is not valid xml to have multiple non-unique attributes on the same element. In other words,

<div ng-controller="a" ng-controller="b">

is invalid. But what about when we do

<div id="a" ng-controller="a">
    <div id="b" ng-controller="b">
        <div id="c">

This is valid xml/HTML, but it is not assigning two controllers to the div with id c. This is called Nested Controllers.

Comments

0

I've just been faced with the same problem trying to code the tabs with container and I'm going to use a directive, which wraps the content using ng-transclude - this way it will be just one controller for the content and I'll then define another controller on the directive, which can be re-used multiple times with whatever content necessary.

Comments

0

this is surely gonna work...

<!DOCTYPE html>
<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular.min.js"></script>
</head>
<body ng-app="myNgApp">
    <div id="div1" ng-controller="anotherController">
        Message: {{message}} <br />       
        <div id="div2" ng-controller="myController">
            Message: {{message}}
        </div>
    </div>

      <div id="div3" ng-controller="myController">
        Message: {{message}}
    </div>

      <div id="div4" ng-controller="anotherController">
        Message: {{message}}
    </div>

    <script>
        var ngApp = angular.module('myNgApp', []);

        ngApp.controller('myController', function ($scope) {
            $scope.message = "This is myController";       
        });

        ngApp.controller('anotherController', function ($scope) {
            $scope.message = "This is anotherController";       
        });
    </script>
</body>
</html>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.