2

I'm using AngularJs UI-Router for my app, but I'm with a problem where the parent's controller isn't initiated.

This is my state structure:

.state('main', {
    abstract: true,
    controller: 'MainController',
    controllerAs: 'vm',
    resolve: {
        config: function($timeout){
            return $timeout(function() {
                return console.log('loaded')
            }, 1000);
        }
    }
})
.state('home', {
    parent: 'main',
    url: '/Home',
    views: {
        'content@': {
            templateUrl: 'view/home.html'
        }
    }
})
.state('contact', {
    parent: 'main',
    url: '/Contact',
    views: {
        'content@': {
            templateUrl: 'view/contact.html',
        }
    }
})

The template home.html and contact.html are displaying on the view just fine. But inside the MainController I have just a console.log but it doesn't appear on the console.

If I make some changes, I can make it work. This is the working example:

.state('main', {
    abstract: true,
    views: {
        'main': {
            template: '<div ui-view="content"></div>',
            controller: 'MainController',
            controllerAs: 'vm'
        }
    }
[...code...]

.state('home', {
    parent: 'main',
    url: '/Home',
    views: {
        'content': {
[...code...]

This way, everything works as expected, The view appear and the console from the controller also appear.

But it doesn't seem "right" because I need to create a template just to hold the child states.

Is there a way to make it work with the first option?

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
celsomtrindade
  • 4,501
  • 18
  • 61
  • 116
  • i've had problems using `controllerAs` try to use `controller: MainController as vm` – Paulo Galdo Sandoval Sep 01 '16 at 02:59
  • @PauloGaldoSandoval Since i was using the controller just for tests and to print a console, i tired to use it just as `controller: 'MainController'`, without the controllerAs, but got the same results. – celsomtrindade Sep 01 '16 at 03:11

1 Answers1

1

Well, to answer:

... Is there a way to make it work with the first option?

Have to say: NO. The point is:

Scope Inheritance by View Hierarchy Only

Keep in mind that scope properties only inherit down the state chain if the views of your states are nested. Inheritance of scope properties has nothing to do with the nesting of your states and everything to do with the nesting of your views (templates).

It is entirely possible that you have nested states whose templates populate ui-views at various non-nested locations within your site. In this scenario you cannot expect to access the scope variables of parent state views within the views of children states.

So, what happened is - the child state views: {} definition:

.state('contact', {
    parent: 'main',    
    views: {
        'content@': {
    ...

... forced child to skip parent view. Not parent state. It skips a parent view. There is no parent view, from which it could inherit the $scope.

The view of a child state 'contact', is injected directly into root (index.html) ui-view="content", it will not trigger parent view...

So, use the second approach, which is absolutely correct, to achieve what is exepected

Check also these for farther details and working examples:

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • 1
    I knew about the inheritance hierarchy, but I tought it was only applied to the resolve data, not to all views and controllers. Thanks for the great answer explaning what is actually happening! – celsomtrindade Sep 01 '16 at 12:18