The concept as you presented that above, is working. I created sample working plunker to show that this kind of state flow is working:
$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",
})
These links work and do navigate as expected:
<a href="#/app/dashboard">
<a href="#/app/product">
<a href="#/app/product/new">
The only way, how I made this link
<a href="#/app/product/new/">
to navigate to its parent (as stated in the question), is by 1) having the default rdirection like this:
$urlRouterProvider.otherwise('/app/product');
And as example above shows - by using wrong link
// check the trailing /
<a href="#/app/product/new/">
// this will work
<a href="#/app/product/new">
Summary, the concept is ok. There is no built in reason to navigate from #/app/product/new
to #/app/product
Check it here
EXTEND
As provided - this is the broken plunker. Which I fixed here
The first adjustment was the index.html - cleanup
- remove wrong elements
- and use NOT MIN angular to see the issue
index.html:
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<!--script>document.write('<base href="' + document.location + '" />');</script-->
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js@1.4.x" 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>
And then, the real issue was wrong reference name 'ui-router' - it should be 'ui.router'
app.js
// wrong
var app = angular.module('plunker', ['ui-router'])
// working
var app = angular.module('plunker', ['ui.router'])
(Based on the comments) - there is another important featue - target <div ui-view>
. This was added into parent state 'app.product'
.
Reason is - each state (including any child or grand child) must be injected somewhere. And by default it is its parent. So parent 'app.product'
should contain the ui-view
target - for its child 'app.product.new'
.
There are other techniques - called named views and absolute naming which could be in detail observed here:
Working version is here