15

Edited with more details

Newbie question here, I am sure. I am trying to do something that I thought would be straightforward, but I am not getting anywhere.

Basically, I have a parent state with several child states. I want to load some data in the resolve of the parent state so that it is available to all child states. To do this, I need a parameter (context) that is passed to the child state to be available. I am getting it via $state.params. the code (some omitted for clarity) is like this:

.state('pbr', {
    url: "/pbr",
    templateUrl: "pbr/pbr.html",
    controller: "pbrBaseCtrl",
    abstract: true ,
    resolve: {
        dpts: function(NavDPT, $state) {
               return NavDPT.query({context: $state.params.context}).$promise;
              }
        }    

})
.state('pbr.review', {
        url: "/review/{context}?div",
        templateUrl: "pbr/pbr-review.html",
        controller: "pbrReviewCtrl"
    })

From what I understand, $state.params should contain the passed parameters for the parent and child states whereas $stateParams have the params only for the active state.

Anyway, what I am seeing is that $state.params does not get populated before the resolve happens, and thus the fetch of data fails. It does eventually get populated though. I can't seem to work out a way to wait for $state.params to be available before getting the data. I have tried wrapping the thing in a timeout, etc.

I have tried to instead use query params, and have specified the query param at the parent level, and I observe this same behavior - newcontext is not available yet when the resolve happens.

 .state('pbr', {
            url: "/pbr?newcontext",
            templateUrl: "pbr/pbr.html",
            controller: "pbrBaseCtrl",
            abstract: true ,
            resolve: {
                dptsResource: 'NavDPT',
                dpts: function(dptsResource, $state, $log) {
                    $log.info("state.params is also ",$state.params);
                    return dptsResource.query({context: $state.params.newcontext}).$promise;
                }
            }

        })

Thanks.

Amirhossein Mehrvarzi
  • 18,024
  • 7
  • 45
  • 70
Chris Perreault
  • 213
  • 2
  • 7
  • 1
    Well, I would say, that the issue here is pretty clear. You are trying to touch the child params... NOT defined in parent ... inside of the parent state rosolution event... From my perspsective: Do **not** do it. That design simply does not suite here. Either move the param one level up (define it on a Parent state) or just resolve the *dpts* for a `pbrReviewCtrl` (child state) – Radim Köhler Jun 19 '14 at 08:35
  • I'm sorry - I left out that I have also tried to use query parameters instead of path parameters, and I have specified the parameter at the parent level, and I observe the same issue. – Chris Perreault Jun 19 '14 at 09:52
  • Ok, not a problem ;) pleaes look at this Q & A: http://stackoverflow.com/questions/24275203/ there is a link to plunker, observe it and you will se that it is working ;) See : *ChildCtrl* – Radim Köhler Jun 19 '14 at 09:54
  • Thanks a lot, I will have a look. – Chris Perreault Jun 19 '14 at 09:57
  • If none meanwhile will give you any suitable answer, and you still will need make it running, I will try to create a working plunker for you... a bit later ;) – Radim Köhler Jun 19 '14 at 09:58
  • You, sir, have saved my day. I don't know exactly what my problem was, but it works now, exactly as it should. – Chris Perreault Jun 19 '14 at 10:08
  • Take a look at the accepted answer on http://stackoverflow.com/questions/24638344/angularui-router-pass-url-params-to-abstract-state-while-calling-child-state. It worked for me. – ilia Mar 05 '15 at 23:31

2 Answers2

6

There is an example showing how we can acces the $stateParams even in resolve function, but they must be defined in current or parent state (not in child)

So, these are the states:

  $stateProvider
    .state('pbr', {
        // we define 2 params oldContext and newContext
        url: "/pbr/{oldContext}?newContext",
        ...
        resolve: { 
            // here we can get all params defined for our state
            dpts: function($state, $stateParams) { 
                return {
                  oldContext : $stateParams.oldContext,
                  newContext : $stateParams.newContext,
                }
            }
        }
    })
    // child will have even the context as 3rd param
    .state('pbr.review', {
      url: "/review/{context}",
      ...
    })

These are the ways how to call them:

// via ui-sref
ui-sref="pbr.review({oldContext: 'abc1', newContext : 'def1', context : 'xyz1'})"
ui-sref="pbr.review({oldContext: 'abc2', newContext : 'def2', context : 'xyz2'})"

// via href
href="#/pbr/abc1/review/xyz1?newContext=def1"
href="#/pbr/abc2/review/xyz2?newContext=def2"

Observe more in that plunker

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
0

Just define params on the parent level. You will then have access to them both on parent and child levels.

PARENT:

{
    state: 'modal',
    config: {
        url: '/modules?person_id&encounter_id',
        controller: 'ModalController',
        controllerAs: 'vm',
        templateUrl: 'app/modal/views/modal.html',
        abstract: true
    }
}

CHILD:

{
    state: 'modal.micro',
    config: {
        url: '/micro',
        controller: 'MicroController',
        controllerAs: 'vm',
        templateUrl: 'app/micro/views/micro.html'
    }
}

ACCESS FROM MODAL CTRL (example):

if (condition) {
    vm.currentPerson = _.find(DashboardModel.pane1Data.DATA_REC.DATA_LIST, function (person) {
        return person.PERSON_ID == $stateParams.person_id;
    });
}

ACCESS FROM CHILD CTRL (example):

if (condition) {
    vm.currentPerson = _.find(DashboardModel.pane1Data.DATA_REC.DATA_LIST, function (person) {
        return person.PERSON_ID == $stateParams.person_id;
    });
}
Marcin Rapacz
  • 616
  • 8
  • 12