I have a parent view that contains a navbar, and inside of that view I have a I want
In this case, I would suggest to go with view inheritance
(not controller
, not state
). Check more details here:
What we would need is a 'root'
state. It will be the super parent of any other state
(states family). This could be the state definition:
$stateProvider
.state('root', {
abstract: true,
templateUrl: 'layout.tpl.html',
controller: MyNamespace.RootCtrl,
})
.state('login', {
parent: "root",
url: "/login",
templateUrl: 'tpl.html',
controller: MyNamespace.LoginCtrl,
})
.state('home', {
parent: "root",
url: "/home",
templateUrl: 'tpl.html',
controller: MyNamespace.HomeCtrl,
})
even some other state hierarchy will start with that 'root'
state:
$stateProvider
.state('parent', {
parent: "root",
url: "/parent",
templateUrl: 'tpl.html',
controller: MyNamespace.ParentCtrl
})
.state('parent.child1', {
url: "/child1",
templateUrl: 'tpl.html',
controller: MyNamespace.Child1Ctrl
})
.state('parent.child2', {
url: "/child2",
templateUrl: 'tpl.html',
controller: MyNamespace.Child2Ctrl
})
We can see many controllers:...
being defined, and here they are:
module MyNamespace {
// the real SUPER parent of all states
// but it is about VIEW inheritance (its $scope)
// not about controller hierarchy
export class RootCtrl extends BaseController {
}
export class HomeCtrl extends BaseController {
}
export class LoginCtrl extends BaseController {
}
export class ParentCtrl extends BaseController {
}
export class Child1Ctrl extends BaseController {
}
export class Child2Ctrl extends BaseController {
}
}
As mentioned in the snippet comment - there is inheritance, but just on a code level. The passed $scope
is inherited by view hierarchy.
The first controller in the view hierarchy is RootCtrl
which will in fact be the only, who will assign (create) the shared reference model rootSetting : {}
And they all derive from this one controller base:
module MyNamespace {
export interface IRootSetting {
hideNavbar: boolean;
}
export interface IMyRootScope extends ng.IScope {
rootSetting: IRootSetting
}
export interface IBaseScope extends IMyRootScope {
}
export class BaseController {
public hideNavbar: boolean;
static $inject = ['$scope', '$state'];
constructor(public $scope: IBaseScope,
protected $state: ng.ui.IStateService) {
// will be in fact assigned in the RootCtrl only
// all others (children) will get that reference
// via scope inheritance
$scope.rootSetting = $scope.rootSetting || {hideNavbar: false};
if ($state.current.url === '/login') {
this.$scope.rootSetting.hideNavbar = true;
} else {
this.$scope.rootSetting.hideNavbar = false;
}
}
}
}
Having that in place, with this root template:
<div>
<div ng-if="!rootSetting.hideNavbar">
... // navbar
</div>
<div ui-view="">
// standard content of child views
</div>
</div>
We can see, that here we evaluate the shared reference model rootSetting
and its property hideNavbar
This is the real advantages of view inheritance
coming with UI-Router
.
Check it in action here