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="[email protected]" 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