In the customers view I have a create customer button which should load a customers.create.html
partial view where the customers.html
is positioned
We need to use absolute view name, to precisely inform ui-router, where to (re-)place the child template. (check this example) Read more here:
cite:
// absolutely targets the unnamed view in root unnamed state.
// <div ui-view/> within index.html
"@" : { }
So, the root view name is empty string, which for a child could be represented as '@'
$stateProvider
.state('customers', {
url: "/customers",
templateUrl: "../views/customers.html",
controller: ['$scope', '$stateParams', '$state',
function($scope, $stateParams, $state) {
}]
})
.state('customers.create', {
url: "/create",
views: {
'@': {
templateUrl: "../views/customers.create.html"
}
}
})
See more here in this plunker
Extend. Any state defintion, is defining the view name, where its template/templateUrl/templateProvider belongs to. If there is only one template to be injected into parent ui-view="" (unnamed) we can use this syntax:
.state('customers', {
url: "/customers",
templateUrl: "tpl.customers.html",
controller: ....
})
which is equal to this syntax:
.state('customers', {
url: "/customers",
views: {
// explicit information that we target unnamed view
'': {
templateUrl: "tpl.customers.html",
controller: ...
}
}
})
So, if we do have to ui-view
targets on the root level
<h4 data-ui-view="header"></h4>
<div data-ui-view=""></div>
we can define states like this:
$stateProvider
.state('customers', {
url: "/customers",
views: {
'header': {
template: '<div>customers</div>',
// controller...
},
'': {
templateUrl: "tpl.customers.html",
controller: ...
}
}
})
.state('customers.create', {
url: "/create",
views: {
'header@': {
template: "<div>create</div>",
},
'@': {
templateUrl: "tpl.customers.create.html",
}
}
})
;
See extended example plunker
EXTEND: to give THE answer to a comment:
... I have no idea why it works now here...did the same as before I just put this in my code: '@': { templateUrl: "tpl.customers.create.html", }..
As mentioned here: View Names - Relative vs. Absolute Names:
Behind the scenes, every view gets assigned an absolute name that follows a scheme of
viewname@statename
, where viewname is the name used in the view directive and state name is the state's absolute name, e.g. contact.item. You can also choose to write your view names in the absolute syntax.
So what happens?
The ui-view=""
placed in index.html
is getting the absolute name "@". Which does consist of three parts (while only one char). The delimiter is @
, the chars left from it represent the viewName, the chars on a right side represent the stateName
Having in a state 'customers'
a view, with ui-view="header"
its absolute name would be: "header@customers"
. So any child state can target this view with its own tamplate/tempalteUrl/templateProvider
Having a state 'customers'
with unnamed template ui-view=""
its aboslute name would be "@customers"
(left side from @ is unnamed empty string). If child state like 'customers.create'
would like to target this view,
it can use one of these :
views : {
"@customers" : {
template: ....
}
}
// or
template: ....
because the second just uses implicit notation, which will end up in "" (no vie name) + "@" (delimiter) + "customers" (parent stateName) == "@customers"
4. we can target the root (index.html) using the same notation.
The root name is "" and while the view Name is "" we end up in "" + "@" + "" == "@"
. And that's why this magical setting does the job to place our view into root ui-view=""
index.html via "@"