8

I have states defined as below in my angularjs app using angular ui router state provider. And, I would like to define multiple states with the same configuration ie. with the same template and controller.

$stateProvider
        .state('parent', {
            templateUrl: 'parent.html',
            abstract: true,
            parent: 'apm'
        })
        .state('parent.list', {
            abstract: true,
            url: '/list',
            templateUrl: 'list.html',
            controller: 'ListCtrl'
        })

        .state('parent.list.closed', {
        url: '/q',
        templateUrl: 'closed.html'
        })

        .state('parent.list.details', {   // would like to have same template, controller on different state parent.details without list
            url: '/:id/:name',
            abstract: true,
            templateUrl: 'details.html',
            controller: 'DetailsCtrl',
            resolve: {
                .....
                .....
            }
        })
        .state('parent.list.details.data', { // would like to have same template, controller on different state parent.details.data without list
          url: '/details',
          views : {
            'view1' : {
              templateUrl : 'view1.html'
            },
            'view2' : {
              templateUrl : 'view2.html',
              controller : 'View2Ctrl'
            },
            'view3' : {
              templateUrl : 'view3.html'
            },
            'view4' : {
              templateUrl : 'view4.html'
            }
          }
        })

Is it possible to do something like

.state(['parent.list.details', 'parent.details'], {   
            url: '/:id/:name',
            abstract: true,
            templateUrl: 'details.html',
            controller: 'DetailsCtrl',
            resolve: {
                .....
                .....
            }
        })

Any help or suggestions?

user3701057
  • 395
  • 1
  • 6
  • 22
  • why don't you extract the common options to a plain javascript variable or even an angular constant? I guess you're doing to dry up sake, right? – goreorto Mar 13 '15 at 23:28

2 Answers2

7

Each state needs to be defined in it's own .state() method. You will run into multiple problems trying to do it the way you listed above. Most importantly would be the url.

You can simply do this:

    .state('parent.list', {   
        url: '/list',
        abstract: true,
        templateUrl: 'details.html',
        controller: 'DetailsCtrl',
        resolve: {
            .....
            .....
        }
    .state('parent.list.details', {   
        url: '/:id/:name',
        abstract: true,
        templateUrl: 'details.html',
        controller: 'DetailsCtrl',
        resolve: {
            .....
            .....
        }
    })

While the code is not condensed or efficient in the sense you have to declare the controller and partial used on each state, it is necessary because each state needs its own .state() method

Jacob Carter
  • 711
  • 5
  • 12
  • Thanks for the quick response. My only concern was to repeat bunch of lines of code for the new states I want. – user3701057 Mar 13 '15 at 23:26
  • Yeah like I was saying it isn't the most efficient but because uiRouter requires the `.state()` method to be declared for each state I don't see a way around it. Here is a quote direct from uiRouter's wiki _ "States often have things in common, and the primary way of factoring out these commonalities in this model is via the state hierarchy, i.e. parent/child states aka nested states." – Jacob Carter Mar 13 '15 at 23:31
  • if same controller is bind with different states, then the functions that execute on bind like: getting list from server will be called again and again, that is what I am in problem now. What could be a possible solution? – 89n3ur0n Oct 24 '15 at 08:33
3

I wanted the same and made it like this:

//add a new Function to the object $stateProvider
               $stateProvider.states = (statesArr, obj) => {

                   for (var i in statesArr) {
                       var state = statesArr[i];

                       $stateProvider.state(state, obj);
                   }

                   return $stateProvider;
               };


//use the new function
               $stateProvider

               .states(["main", "main.test"], {
                   url: '/main',
                   templateUrl: 'modules/ViewContainer.html',
                   controllerAs: 'currentCtrl',
                   controller: 'MainCtrl'
               })
Tobias Koller
  • 2,116
  • 4
  • 26
  • 46
  • 1
    work great, i had to clone the state object to make it work with $state.go('^.mystate'); example with underscore : $stateProvider.state(state, _.clone(obj)); – dam1 Oct 18 '16 at 14:58