简体   繁体   中英

AngularJS/UI-Router: How do I use one controller with multiple named views?

I have a child state that fills up named views in the parent state (header, content). They both share the same data, however, and I don't want make a redundant second controller but seems like that's one of my only options. I could just use one view but it would then have too much markup which looks messy.

I read the docs here and the example they showed is for each view in the state to have it's own controller.

This is not ideal for my scenario. For example, ui-router says I have to do this:

.state('root.profile', {
    url: '@:slug',
    views: {
        'header': {
            templateUrl: 'app/profile/profile-header.html',
            controller: 'ProfileHeaderController as profileHeader'
        },
        'content': {
            templateUrl: 'app/profile/profile-body.html',
            controller: 'ProfileBodyController as profileBody'
        }
    }
});

.. and I'd much rather do this:

.state('root.profile', {
    url: '@:slug',
    views: {
        'header': {
            templateUrl: 'app/profile/profile-header.html'
        },
        'content': {
            templateUrl: 'app/profile/profile-body.html'
        }
    },
    controller: 'ProfileController as profile'
});

The second option works better for me because as I said they share the same data and I would rather not reproduce a lot of the same logic twice, but unfortunately it doesn't work.

I am already using a service for the one controller. I wouldn't want to have to create another service just to store one set of values to use in both controllers cause that's still not really DRY.

Is there any work-around for something like this?

Considering you code examples, I don't see how this statement is false: "they share the same data and I would rather not reproduce a lot of the same logic twice" .

1) they share the same data : Since you have a service, I assume the service stores the current data state, which means that the controllers do share the same data.

2) rather not reproduce a lot of the same logic twice : Your views are referencing the same controller, but different instances, which means that you don't have to reproduce any logic.

"I am already using a service for the one controller. I wouldn't want to have to create another service just to store one set of values to use in both controllers" . If you would make that services a factory, which is a singleton, the same instance would be passed in to each controller that uses the factory-service.

However, I see one possible solution you could do for resolving data and defining controller as a parent to the profile state. This, by having another state between root and root.profile state. In the example below the two views ( profile-body.html and profile-header.html ) can now use the same instance of the ProfileController .

.state('root', { .. })
.state('root.profile', {
    abstract:true,
    controller:'ProfileController as profile',
    resolve: {
       profile:function(yourProfileDataService) {
           //Resolve profile data
       }
    }
})
.state('root.profile.view', {
    url: '@:slug',
    views: {
        'header': {
            templateUrl: 'app/profile/profile-header.html'
        },
        'content': {
            templateUrl: 'app/profile/profile-body.html'
        }
    }
});

As seen in the example, I also suggest the usage of the resolve property which resolves the data before instantiating the controller, and then injects it into the controller. Resolve docs .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM