Angular UI router - does a nested view's contr

2019-08-05 16:38发布

Here's my UI-Router configuration. I have a main products view and two nested states underneath that. I want each nested view to have its own controller, but I also want to be able to inherit some basic information from the parent controller (productsCtrl). My assumption would be that I could access productsCtrl from productShowCtrl, but it keeps coming back as undefined. Do productsCtrl and productShowCtrl not have a parent-child relationship by default?

var myProducts = angular.module('Products', [
  'ProductsShow'
])
  .config(function($stateProvider, $urlRouterProvider){
    $stateProvider.state('store.products', {
        url: '/products',
        views: {
          'subhead@': {
            templateUrl:'products/list/subhead.tmpl.html'
          },
          'content@': {
            templateUrl:'products/list/list.tmpl.html',
            controller: 'ProductsCtrl as productsCtrl'
          }
        }
    })
    .state('store.products.create', {
      url: '/create',
      views: {
        'subhead@': {
          templateUrl: 'products/create/subhead.tmpl.html'
        },
        'content@': {
          templateUrl: 'products/create/create.tmpl.html'
        }
      }
    })
    .state('store.products.show', {
      url: '/:productId',
      views: {
        'subhead@': {
          templateUrl: 'products/show/subhead.tmpl.html'
        },
        'content@': {
          templateUrl: 'products/create/create.tmpl.html',
          controller: 'ProductShowCtrl as productShowCtrl',
        }
      }
    });
  });

ProductsCtrl (for the main products view):

myProducts.controller('ProductsCtrl', function($stateParams) {
    var productsCtrl = this;
    productsCtrl.parentTest = "PARENT";
});

ProductsShowCtrl (for the child view):

angular.module('ProductsShow', [])
  .controller('ProductShowCtrl', function($stateParams) {
      var productShowCtrl = this;
      productShowCtrl.childTest = "CHILD";

      console.log('parent: ', productsCtrl.parentTest);
  });

I can't access productsCtrl.parentTest from ProductShowCtrl. How can I access it?

3条回答
Fickle 薄情
2楼-- · 2019-08-05 17:09

Please note that from the ui-Router official docs

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.

So you can not have the scope variables in above way. If you wants to share data across the states you can do in following ways :

1). Any time you need to share data across states you will need to create a service/factory that you can instantiate in your controllers associated with those states. The factory will consist of basic getters and setter for the different data you need to share. Just like when you build getters and setters in java to share across classes.

Demo : Working plunker with this approach.

2). You can set a global variable with $rootScope. It will be accessible everywhere since its global, I strongly advise you don't do this but though I would point it out to you anyway.

3).When a state is "active"—all of its ancestor states are implicitly active as well.So you can build your states considering the parent-child relationship and share data across scopes in hierarchical manner.

Demo : Working plunker with mentioned approach.

查看更多
叼着烟拽天下
3楼-- · 2019-08-05 17:16

The $scope doesn't work like that. They don't have a parent-child relationship by default like you asked. You can read more about it in the angular api docs. The $rootScope has, but still it's bad practice in my opinion.

What you should do in angular when you want to access a variable in two different controllers like your trying you should create a service (factory) to do that.

Maybe you should have a products service in which you could declare variables and functions to access those variables in the conrollers.

查看更多
ら.Afraid
4楼-- · 2019-08-05 17:18

There are related Q & A:

I created special working plunker

The example here with controllerAs could be like this:

The state defintion:

 .state("main", {
      controller:'mainController',
      controllerAs:'mainCtrl',
      url:"/main",
      templateUrl: "main_init.html"
  })  
  .state("main.1", {
      controller:'childController',
      parent: 'main',
      url:"/1",
      templateUrl: 'form_1.html'
  })  
  .state("main.2", {
      controller:'childController',
      parent: 'main',
      url: "/2",
      templateUrl: 'form_2.html'
  }) 

Main controller will define the Model:

app.controller('mainController', function ($scope) {
  var Model = {Name : "xxx"}; // controller property Model
})

And in form_1 or form_2 we can access that model with controllerAs syntax:

<div>
  <h5>Child state FORM 2</h5>
  <pre>{{mainCtrl.Model}}</pre>

  Change the value in a child state FROM 2
  <input ng-model="mainCtrl.Model.Name" />
</div>

Where mainCtrl.Model represents the reference to parent controller (inside of our and its $scope)

Check it here

查看更多
登录 后发表回答