13

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...

burnaDLX
  • 171
  • 1
  • 3
  • 10

2 Answers2

17

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>
Rémi Becheras
  • 14,902
  • 14
  • 51
  • 81
  • Okay, this explanation helped me a lot, I would accept it as the final answer – burnaDLX May 28 '15 at 09:31
  • Well, so in order to `accept` the answer you can click the "check" symbol on the left of my post, it will pass to green marking the answer as accepted. Additionnaly you can upvote clicking the up arrow just next to the check icon. – Rémi Becheras May 28 '15 at 09:35
  • Alright, I thought I have to upvote your comment to let the arrow become green (and my reputation is to low to do so...). – burnaDLX May 28 '15 at 09:38
  • Ok you accepted the answer. Indeed, you are new on the site and your reputation points are not enough to upvote but it's ok! I upvoted your question, and you accepted my answer so your reputation will raise by some points. In some days you will earn more privileges like up/down votes. I encourage you to read the (very well made) help center. Have a nice day! – Rémi Becheras May 28 '15 at 09:43
  • 1
    Thx for the friendly weIcome and the reference. I, too, wish you a very good day! – burnaDLX May 28 '15 at 09:58
9

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'
                }
            }
        })
Ioana Cucuruzan
  • 845
  • 1
  • 8
  • 21