18

I have an Angular App using the great ui-router.

My setup looks like:

.config( function ($stateProvider, $urlRouterProvider) {

    $stateProvider

    // PROJECT DETAIL
    .state('project', {
        url: '/project/:projectId/',
        resolve: {
            /* some base api calls */
        },
        views: {
            'task-list': {
                templateUrl: 'partials/task_list.tmpl.html',
                controller: 'TaskListCtrl',
                resolve: {
                    tasks: function ($stateParams, ConcernService) {
                        return ConcernService.get('project-tasks/', $stateParams.projectId);
                    },
                }
            },
            'concern-instance': {
                /* some resolved variables */
            }
        }
    })
    .state('project.task', {
        url: 'task/:taskId/',
        views: {
            'concern-instance@': {
                /* some different resolved variables */
            },
        }
    })

This all works like butter. However in my task_list template when in state project.task, I want to be able to access the taskId param so I can highlight active nav links, even when the url is #/project/123/task/456/ the taskId is empty. I understand that this is because templates only have access to params declared for that state. So if I want to get the taskId in the project.task state, how should I do it? Do I need to re-declare the task-list in project.task?

halfer
  • 19,824
  • 17
  • 99
  • 186
Darwin Tech
  • 18,449
  • 38
  • 112
  • 187
  • 2
    It's an annoying problem. You could remove the url for the parent state, and declare full urls for the child states, if you don't need the state param in the parent controller/template. If you do, then I guess you could just put the state param in the scope in a variable to be accessed by the children. – aet Apr 08 '14 at 20:37
  • 1
    We're running into the same problem as you describe. You probably already know by now, but you can in fact get to all of your parameters via `$state.params`. But, if you're like me, it won't sit well with you to get your parameters in different ways throughout your controllers. The closest thing I've found so far in the [documentation](https://github.com/angular-ui/ui-router/wiki/URL-Routing#stateparams-service/) describes the opposite issue of a parent state's param not available to the child state. Did you ever figure this out (via `$stateParams`)? – Manny Sep 08 '14 at 15:45
  • Did you ever figured this out? I am also having same problem. – pankaj Jan 07 '15 at 13:55

3 Answers3

14

In the UI-Router documentation here they explain that

"the $stateParams object will only contain the params that were registered with that state."

You can only have access to parent state parameters in a child state using the resolve property on the parent.

Put this on your 'project' state (parent):

...    
resolve: {
    // Expose projectId parameter to child states
    projectId: ['$stateParams', function ($stateParams) {
        return $stateParams.projectId;
    }]
},

Then inside your controller for your state 'project.task' (child) you should have access to both

$stateParams.projectId

and

$stateParams.taskId
dwp4ge
  • 1,963
  • 22
  • 27
4

I have noticed $state.params contains the child state params. Can't seem to find any documentation on it. It just works

Ladmerc
  • 1,158
  • 11
  • 18
-1

How are you trying to access the taskId? It should be like this, taken from official documentation:

$stateProvider
    .state('contacts.detail', {
        url: "/contacts/:contactId",
        templateUrl: 'contacts.detail.html',
        controller: function ($stateParams) {
            // If we got here from a url of /contacts/42
            expect($stateParams).toBe({contactId: 42});
        }
    })
AD.Net
  • 13,352
  • 2
  • 28
  • 47