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?
There are related Q & A:
- ui router - nested views with shared controller
- How do I share $scope data between states in angularjs ui-router?
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
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.
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.