The method you described above is effective. I have created a working plunker to demonstrate the functionality of this state flow:
$stateProvider
.state('app',{
url: '/app',
templateUrl: 'views/app.html',
abstract: true
})
.state('app.dashboard', {
url: '/dashboard',
templateUrl: 'views/dashboard.html'
}).state('app.product', {
url: '/product',
templateUrl: "views/product.html",
}).state('app.product.new', {
parent: 'app.product',
url: '/new',
templateUrl: "views/add_product.html",
})
The provided links work correctly and navigate as expected:
<a href="#/app/dashboard">
<a href="#/app/product">
<a href="#/app/product/new">
To ensure that the link
<a href="#/app/product/new/">
navigates to its parent (as specified in the question), you need to set the default redirection like this:
$urlRouterProvider.otherwise('/app/product');
If you use the incorrect link format like
// check the trailing /
<a href="#/app/product/new/">
// this will work
<a href="#/app/product/new">
In conclusion, the concept works well. There is no inherent reason for navigating from #/app/product/new
to #/app/product
You can test it here
EXTEND
This is the faulty plunker originally provided. I have fixed it here
The first change was made to index.html - cleaning up unnecessary elements
- Deleting incorrect elements
- Using the full version of angular to pinpoint the issue
index.html:
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<link rel="stylesheet" href="style.css" />
<script data-require="<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a2c3ccc5d7cec3d08cc8d1e2938c968c968cda">[email protected]</a>" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.js" data-semver="1.4.6"></script>
<script data-require="ui-router@*" src="//rawgit.com/angular-ui/ui-router/0.2.15/release/angular-ui-router.js"></script>
<!--<script>-->
<script src="app.js"></script>
</head>
The main issue was found in the wrong module reference name 'ui-router' instead of 'ui.router'
app.js
// Incorrect
var app = angular.module('plunker', ['ui-router'])
// Correct
var app = angular.module('plunker', ['ui.router'])
Another crucial point mentioned in comments was to target <div ui-view>
. This was added to the parent state 'app.product'
.
This ensures that each state (including children) must be injected somewhere, typically its parent. Therefore, the parent state 'app.product'
should contain the ui-view
target for its child state 'app.product.new'
.
For more insights on named views and absolute naming, refer to these discussions:
- Angular UI Router - Nested States with multiple layouts
- Angularjs ui-router not reaching child controller
- Angular ui-router : Container view and Default view
You can find the improved version here