What I want to achieve is have 2 sibling views, where 1 is run-once and the other will get updated.
I have a template like so:
<body>
<ui-view="header />
<ui-view="body" />
</body>
And I have 1 catch-all state:
.state('root', {
params: { … },
resolve: {
data: fn() { … }
},
url: '/{p1:string}/{p2:string}/{p3:string}',
views: {
header: {
controller: 'HeaderCtrl as Header',
templateUrl: '…'
},
body: {
controllerProvider: fn() { … },
templateUrl: fn() { … }
}
}
});
The catch-all state dynamically choses the appropriate controller, data, and template. Everything is hunky-dory except that the HeaderCtrl gets re-executed on every state change. I want it to get executed only once.
I tried creating 2 states, root and base, where the above becomes root.base. I moved the header view to the new root state like so:
.state('root', {
abstract: true,
url: '/',
views: {
header: {
controller: 'HeaderCtrl as Header',
templateUrl: '…'
}
}
})
.state('root.base', {
params: { … },
resolve: {
data: fn() { … }
},
url: '/{p1:string}/{p2:string}/{p3:string}',
views: {
body: {
controllerProvider: fn() { … },
templateUrl: fn() { … }
}
}
});
But then only the parent (root) state engages.
I created working plunker here. You are almost there. This is the updated state def:
Firstly, very important, we have to use absolute naming for child state view name
'body@'
. See:View Names - Relative vs. Absolute Names
Secondly, no url at the parent is specified... that will make it not accessible by url.
Also, abstract is not needed... could be ... but if we would like to use
.when()
it is better to make it non abstract. Check these:Working plunker with the above stuff is here