Assign multiple controller in $stateProvider.state

All we need is an easy explanation of the problem, so here it is.

Probably this is an easy question for advanced angular users, but I did not find this issue somewhere well explained.

So I was restructuring my code, when I realized, I have two controllers in a view, which is not a problem, when controller ‘ACtrl’ is binded by the $stateProvider and controller ‘BCtrl’ is binded in the view by ng-controller. But when I try to assign both of them in the $stateProvider like this:

$stateProvider.state('a.view', {
    url: "/anurl",
    views: {
        'menuContent': {
            templateUrl: "anUrlToMyTemplates",
            controller: 'ACtrl', 'BCtrl'
        }
    }
}); 

or that:

$stateProvider.state('a.view', {
    url: "/anurl",
    views: {
        'menuContent': {
            templateUrl: "anUrlToMyTemplates",
            controller: 'ACtrl',
            controller: 'BCtrl'
        }
    }
});

it won’t work.

I know it would be a solution to make the content of the controllers up to one, but controller ‘ACtrl’ is used somewhere else, too, so I would have to repeat myself somewhere else. How can I solve this…

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Syntaxically, it can’t work. This (syntaxically) could work :

$stateProvider.state('a.view', {
    url: "/anurl",
    views: {
        'menuContent': {
            templateUrl: "anUrlToMyTemplates",
            controller: ['ACtrl', 'BCtrl']
        }
    }
}); 

But AngularJS use ZERO or ONE controller by DOMElement.

You can assign CtrlA for your A view :

$stateProvider.state('a.view', {
    url: "/anurl",
    views: {
        'menuContent': {
            templateUrl: "anUrlToMyTemplates",
            controller: 'ACtrl'
        }
    }
}); 

And then into your A view :

<div data-ng-controller="BCtrl">
    <!-- your view content -->
</div>

That said, for code design purpose, the correct way is to merge the actions of your two controllers in only one if they have to control the same template elements. If they control different parts of the template, use one controller for one part, or a controller for the whole view, and an other for the specific part :

<!-- your view controlled by ACtrl configured in route provider -->
<div> 
    <!-- your view content, part A -->

    <div data-ng-controller="BCtrl">
        <!-- your view content, part B -->
    </div>
</div>

Method 2

Split your layout and use something like:

.state('app.somestate', {
            url : '/someurl',
            views:{
                'menuContent': {
                    templateUrl: 'part1.html',
                    controller: 'ACtrl'
                },
                'otherContent': {
                    templateUrl: 'part2.html',
                    controller: 'BCtrl'
                },
                'someotherContent': {
                    templateUrl: 'part3.html',
                    controller: 'CCtrl'
                }
            }
        })

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply