12

I have a tricky situation here. my parent state and child state are both overriding the same ui view at the top level(index.html). So when it goes to the child state from the parent the scope gets broken(I think?) Basically the parent has a resolve which is stored in the MetricData property that I can't seem to access from the child since its not nested I am assuming. Is there a way to get that metricdata property in the child without having to manually call the same ajax call again in the child

parent state

     .state("home.metric", {
      url: "/category/:categoryId/metric/:metricId/name/:metricName",
      views: {

        'main@': {

          templateUrl:
            function (stateParams){
              //move this to a util function later
              var tempName = unescape(stateParams.metricName);
              tempName = tempName.replace(/\s/g, "-");

              return '../partials/slides/' + tempName + '.html';
            },
          resolve: {
            MetricData: ['MetricService', '$stateParams', 
              function(MetricService,    $stateParams){
                var data = { categoryId : $stateParams.categoryId, metricId : $stateParams.metricId};
                return MetricService.getMetricDetails(data);
              }]
          },
          controllerProvider: 
            function ($stateParams) {
              var tempName = unescape($stateParams.metricName);
              tempName = tempName.replace(/\s+/g, '');

              return tempName + 'Ctrl';
            }
        }
      }

    })

child state

.state("home.metric.detail", {
      url: "/detailId/:detailId/detailName/:detailName",
      views: {

        'main@': {
          templateUrl:
            function ($stateParams){
              //move this to a util function later
              var tempName = unescape($stateParams.detailName);
              tempName = tempName.replace(/\s/g, "-");

              return '../partials/slides/' + tempName + '.html';
            },
          resolve: {
            DetailData: ['DetailService', '$stateParams',
              function(DetailService,      $stateParams){
                var data = { categoryId : $stateParams.categoryId, detailId : $stateParams.detailId};
                return DetailService.getDetails(data);
              }],
            // MetricData: ['MetricService', '$stateParams', 
            //   function(MetricService,    $stateParams){
            //     var data = { categoryId : $stateParams.categoryId, metricId : $stateParams.metricId};
            //     return MetricService.getMetricDetails(data);
            //   }]
          },
          controllerProvider: 
            function ($stateParams) {
              var tempName = unescape($stateParams.detailName);
              tempName = tempName.replace(/\s+/g, '');

              return tempName + 'Ctrl';
            }
        }

      }

    })
atsituab
  • 637
  • 2
  • 7
  • 20
  • try Using $scope.$parent, after a timeout function – Geo Jacob Oct 22 '14 at 18:06
  • @GeoJacob where would I put that. in the controller of the child or in the resolve area? – atsituab Oct 22 '14 at 18:17
  • @GeoJacob actually this doesnt work, the parent is rootscope since the child is overriding the view of the parent. if it was nested in the parent scope.parent would work – atsituab Oct 22 '14 at 18:23

1 Answers1

15

I. The answer to question:

... child since its not nested ... Is there a way to get that metricdata property in the child?

Is based on

What Do Child States Inherit From Parent States?

Child states DO inherit the following from parent states:

  • Resolved dependencies via resolve
  • Custom data properties

Nothing else is inherited (no controllers, templates, url, etc).

in conjuction with

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.

II. While this should be clear now, we still need to find a way how to solve:

... Is there a way to get that metricdata property in the child without having to manually call the same ajax call again in the child..

And I would say, there is also answer. E.g.

.. move the shared views/resolvers to the least common denominator. ..

E.g. we can do it like in this Q & A: Controlling order of operations with services and controllers, see the plunker:

A special grand parent / root state:

$stateProvider
  .state('root', {
    abstract : true,
    // see controller def below
    controller : 'RootCtrl',
    // this is template, discussed below - very important
    template: '<div ui-view></div>',
    // resolve used only once, but for available for all child states
    resolve: {
      user: function (authService) {
          return authService.getUserDetails();
      }
    }
  }) 

Passing resolved stuff into $scope (inherited by each child)

.controller('RootCtrl', function($scope,user){
  $scope.user = user;
})

This is injected on top of our state / view hierarchy, and any child state would profit from it

// any previously root state will just use the above as a parent
.state('index', {
    url: '/',
    parent : 'root',

Check more details here and see it in a working example

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • yeah i saw that as a solution somewhere. looks like I will need to create an additional abstract state to hold all my info. was hoping I could do it without the extra abstract state and just use a service/factory – atsituab Oct 23 '14 at 13:23
  • Service factory... Injected into $rootScope would work as well. But from my perspective this solution is ... cleaner. I'd say.. – Radim Köhler Oct 23 '14 at 13:24