How to display nav menu while using ui router - angularjs

I'm trying to display navigation bar menu items using ng-repeat and I'm using ui router simultaneously, but output is not what I expected.
<!--HTML-->
<body>
<div ng-app="navApp" ng-controller="navCtrl">
<a ng-repeat="item in navItems" ui-sref="{{item.sref}}">{{item.label}}</a>
</div>
<div ng-app="mainApp">
<div ui-view></div>
</div>
</body>
//JS
angular.module('navApp', []).controller('navCtrl', function($scope){
$scope.navItems = [
{'sref': 'home', 'label': 'Home'},
{'sref': 'login', 'label': 'Login'},
{'sref': 'signup', 'label': 'Signup'},
{'sref': 'other', 'label': 'Label'}
];
});
var app = angular.module('mainApp', ['ui.router']);
app.config(function($stateProvider, $urlRouterProvider){
// $urlRouterProvider.otherwise('/');
$stateProvider.state('login', {
url: '/login',
templateUrl:'login.html',
controller: function($scope) {
$scope.message = 'Login Page'
}
}).state('signup', {
url: '/signup',
templateUrl:'signup.html',
controller: function($scope) {
$scope.status = 'Signup Page'
}
}).state('home', {
url: '/',
template:'Home Page'
}).state('other', {
url: '/other',
template:'Other Page'
});
});
I'm getting output as:
HomeLoginSignupLabel
Here sref are not working as href. Using static navigation menu instead of displaying dynamically then everything is working fine. I think both apps are executing at same causing this issue.

use some navbar like bootsrap or semantic-ui etc.
bootstrap example :
<body>
<div ng-app="navApp" ng-controller="navCtrl">
<nav class="navbar navbar-inverse">
<ul class="nav navbar-nav">
<li ng-repeat="item in navItems"><a ui-sref="{{item.sref}}">{{item.label}}</a></li>
</ul>
</nav>
<div ng-app="mainApp">
<div ui-view></div>
</div>
</body>

Related

AngularJS controller not properly loaded during ng-Route otherwise()

I'm learning an example of a single page application using angularjs. Here's the relevant code:
index.html
<!DOCTYPE html>
<html ng-app="app">
<head>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"/>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.0/css/font-awesome.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.8/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular-route.js"></script>
<script>
var app = angular.module('app', ['ngRoute']);
app.config(function ($routeProvider) {
// configure the routes
$routeProvider
.when('/', {
// route for the home page
templateUrl: 'pages/home.html',
controller: 'homeController'
})
.when('/about/', {
// route for the about page
templateUrl: 'pages/about.html',
controller: 'aboutController'
})
.when('/contact/', {
// route for the contact page
templateUrl: 'pages/contact.html',
controller: 'contactController'
})
.otherwise({
// when all else fails
templateUrl: 'pages/routeNotFound.html',
controller: 'notFoundController'
});
});
app.controller('homeController', function ($scope) {
$scope.message = 'Welcome to my home page!';
});
app.controller('aboutController', function ($scope) {
$scope.message = 'Find out more about me.';
});
app.controller('contactController', function ($scope) {
$scope.message = 'Contact us!';
});
app.controller('notFoundController', function ($scope) {
$scope.message = 'There seems to be a problem finding the page you wanted';
$scope.attemptedPath = $location.path();
});
</script>
</head>
<body ng-controller="homeController">
<header>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="/">My Website</a>
</div>
<ul class="nav navbar-nav navbar-right">
<li><i class="fa fa-home"></i> Home</li>
<li><i class="fa fa-shield"></i> About</li>
<li><i class="fa fa-comment"></i> Contact</li>
</ul>
</div>
</nav>
</header>
<div id="main">
<!-- this is where content will be injected -->
<div ng-view></div>
</div>
</body>
</html>
routeNotFound.html
<div class="jumbotron text-center">
<h1>This is not good</h1>
<p>{{message}}</p>
<p class="has-error">{{attemptedPath}}</p>
</div>
When I click on Home or About or Contact the page renders correctly. But if I visit any other URL, routeNotFound.html is injected correctly to div[ng-view] but the data is not bound. I get:
This is not good
{{message}}
{{attemptedPath}}
It seems notFoundController is not correctly made available to the view when .otherwise() is called inside route. $scope.message and $scope.attemptedPath is not bound to the view.
You are missing $locationService injection in your notFoundController
app.controller('notFoundController', function ($scope,$location /*<--- location injected here*/) {
$scope.message = 'There seems to be a problem finding the page you wanted';
$scope.attemptedPath = $location.path();
});
Here is a full sample:
var app = angular.module('app', ['ngRoute']);
app.config(function ($routeProvider) {
// configure the routes
$routeProvider
.when('/', {
// route for the home page
template: '<h1>My page home</h1><br />{{message}}',
controller: 'homeController'
})
.when('/about/', {
// route for the about page
template: '<h1>My page about</h1><br />{{message}}',
controller: 'aboutController'
})
.when('/contact/', {
// route for the contact page
template: '<h1>My page contact</h1><br />{{message}}',
controller: 'contactController'
})
.otherwise({
// when all else fails
template: '<h1>Not found page</h1><br />{{message}}',
controller: 'notFoundController'
});
});
app.controller('homeController', function ($scope) {
$scope.message = 'Welcome to my home page!';
});
app.controller('aboutController', function ($scope) {
$scope.message = 'Find out more about me.';
});
app.controller('contactController', function ($scope) {
$scope.message = 'Contact us!';
});
app.controller('notFoundController', function ($scope,$location) {
$scope.message = 'There seems to be a problem finding the page you wanted';
$scope.attemptedPath = $location.path();
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"/>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.0/css/font-awesome.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.8/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular-route.js"></script>
<script>
</script>
</head>
<body ng-controller="homeController">
<header>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="/">My Website</a>
</div>
<ul class="nav navbar-nav navbar-right">
<li><i class="fa fa-home"></i> Home</li>
<li><i class="fa fa-shield"></i> About</li>
<li><i class="fa fa-comment"></i> Contact</li>
<li><i class="fa fa-comment"></i> Not found</li>
</ul>
</div>
</nav>
</header>
<div id="main">
<!-- this is where content will be injected -->
<div ng-view></div>
</div>
</body>
</html>

Custom directive not displaying withing a ui-view

I have a custom dircetive "3-test-directive" which I want to call to display a text. When I use this directive in the page partial-home.html, it does not diaplay me with any text from the directive(it seems the directive did not work).
When I use the same code <3-test-directive/> inside of index.htm, the directive is correctly parsed. Why did not the one with the partial-home.html did not work and how can I fix this ?
Demo for this code : https://plnkr.co/edit/wy5gkUlXmbRpyrdqwHwd?p=preview
index.html
<!-- CSS (load bootstrap) -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<style>
.navbar { border-radius:0; }
</style>
<!-- JS (load angular, ui-router, and our custom js file) -->
<script src="https://code.angularjs.org/1.2.13/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.8/angular-ui-router.min.js"></script>
<script src="app.js"></script>
</head>
<!-- apply our angular app to our site -->
<body ng-app="routerApp">
<!-- NAVIGATION -->
<nav class="navbar navbar-inverse" role="navigation">
<div class="navbar-header">
<a class="navbar-brand" ui-sref="#">AngularUI Router</a>
</div>
<ul class="nav navbar-nav">
<li><a ui-sref="home">Home</a></li>
<li><a ui-sref="about">About</a></li>
</ul>
</nav>
<!-- MAIN CONTENT -->
<!-- THIS IS WHERE WE WILL INJECT OUR CONTENT ============================== -->
<div class="container">
<div ui-view></div>
</div>
<div class="text-center">
<p>A tutorial by scotch.io</p>
<p>View the tutorial: AngularJS Routing using UI-Router</p>
</div>
</body>
</html>
app.js
var routerApp = angular.module('routerApp', ['ui.router']);
routerApp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
// HOME STATES AND NESTED VIEWS ========================================
.state('home', {
url: '/home',
templateUrl: 'partial-home.html'
})
// nested list with custom controller
.state('home.list', {
url: '/list',
templateUrl: 'partial-home-list.html',
controller: function($scope) {
$scope.dogs = ['Bernese', 'Husky', 'Goldendoodle'];
}
})
// nested list with just some random string data
.state('home.paragraph', {
url: '/paragraph',
template: 'I could sure use a drink right now.'
})
// ABOUT PAGE AND MULTIPLE NAMED VIEWS =================================
.state('about', {
url: '/about',
views: {
'': { templateUrl: 'partial-about.html' },
'columnOne#about': { template: 'Look I am a column!' },
'columnTwo#about': {
templateUrl: 'table-data.html',
controller: 'scotchController'
}
}
});
});
routerApp.controller('scotchController', function($scope) {
$scope.message = 'test';
$scope.scotches = [
{
name: 'Macallan 12',
price: 50
},
{
name: 'Chivas Regal Royal Salute',
price: 10000
},
{
name: 'Glenfiddich 1937',
price: 20000
}
];
});
You can't include scripts in templates...they get stripped out.
Just register the directive in your js file
var routerApp = angular.module('routerApp', ['ui.router'])
.directive("w3TestDirective", function() {
return {
restrict:'E',
template : "<h1>Made by a directive!</h1>"
};
})
DEMO

angular JS adding image gallery/viewer breaking single page routing

I am newer to Angular so this could be a really simple/stupid issue but after googleing and trying many things I couldnt get it to work.
I believe this may not be directly related to the image viewer but a general issue when trying to add additional functionality injected into the code (like this: angular.module('app', ['angular-flexslider']);) I tried with a couple other things and had same issue so it may be a general issue on how I have my code setup when adding this that is breaking everything including the routing (but routing is the only real functionality I have currently.
If I have stand alone pages for the image viewer it works fine but incorporating it with other code causes the issue.
var app = angular.module('app', ['angular-flexslider']);
if I change the "app" to "app1" it does not cause all routing to break, so it is not the script tags being added that is causing the issue itself, but something with this and how I have the code setup (something is getting cross wired I think).
The code for my pages that are important are:
index:
<!DOCTYPE html>
<html ng-app="app">
<head>
<base href="/" />
</head>
<body>
<link rel="stylesheet" href="styles/styles.css">
<div class="header">
<div class="container">
<img src="/images/DPLogo.jpg" />
<h1>Downriver Panters</h1>
</div>
</div>
<div class="nav-bar">
<div class="container">
<ul class="nav">
<li>Home</li>
<li>History</li>
<li>Coaches</li>
<li>Activities</li>
<li>Calender</li>
<li>Gallery</li>
<li>Fundraisers</li>
<li>Links</li>
<li>Contact Us</li>
<li>Test Styles</li>
</ul>
</div>
</div>
<div class="content">
<div class="container">
<div ng-view>ViewPage</div>
</div>
</div>
<div class="footer">
<div class="container">
© Copyright 2016
</div>
</div>
<!-- this is code for the image viewer that is causing it to break (but also add the app.js file below)-->
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.angularjs.org/1.3.0/angular.js"></script>
<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.min.js"></script>
<script src="//cdn.jsdelivr.net/flexslider/2.2.2/jquery.flexslider-min.js"></script>
<script src="/testing/angular-flexslider.js"></script>
<script src="/scripts/angular.min.js"></script>
<script src="/scripts/angular-route.min.js"></script>
<!-- end of code causing it to break -->
<!-- my main control with the routing -->
<script src="/controllers/mainCtrl.js"></script>
<!-- have to put here?? so below mainCtrl??? cause not working if put on home page -->
<script src="/controllers/homeCtrl.js"></script>
<script src="/controllers/calenderCtrl.js"></script>
<script src="/controllers/coachesCtrl.js"></script>
<script src="/controllers/galleryCtrl.js"></script>
<!-- other file for routing that is causing it to break-->
<script src="/testing/app.js"></script>
</body>
</html>
mainCtrl.js (with my routing code)
(function () {
'use strict';
var app = angular.module('app', ['ngRoute']);
// configure our routes
app.config(['$routeProvider','$locationProvider',
function ($routeProvider, $locationProvider) {
$routeProvider
// catch all go home
.when('/', {
templateUrl: '/partials/home.html',
controller: 'homeController'
})
// route for the home page
.when('/home', {
templateUrl: '/partials/home.html',
controller: 'homeController'
})
// route for the about page
.when('/about', {
templateUrl: '/partials/about.html',
controller: 'aboutController'
})
// route for the contact page
.when('/history', {
templateUrl: '/partials/hisotry.html',
controller: 'hisotryController'
})
// route for the contact page
.when('/coaches', {
templateUrl: '/partials/coaches.html',
controller: 'coachesController'
})
// route for the contact page
.when('/activities', {
templateUrl: '/partials/activities.html',
controller: 'activitiesController'
})
// route for the contact page
.when('/calender', {
templateUrl: '/partials/calender.html',
controller: 'calenderController'
})
// route for the contact page
.when('/gallery', {
templateUrl: '/partials/gallery.html',
controller: 'galleryController'
})
// catch all go home
.when('/fundraisers', {
templateUrl: '/partials/fundraisers.html',
controller: 'fundraisersController'
})
// catch all go home
.when('/links', {
templateUrl: '/partials/links.html',
controller: 'linksController'
})
// route for the contact page
.when('/contactus', {
templateUrl: '/partials/contactus.html',
controller: 'contactusController'
})
// catch all go home
.when('/styletesting', {
templateUrl: '/partials/styleTesting.html',
controller: 'styletestController'
})
// happens when nothing specificed
.otherwise({
redirectTo: '/'
})
// not working/finding sites
// if you don't wish to set base URL then use this
$locationProvider.html5Mode({
enabled: true,
requireBase: true
});
}]);
})();
the code fot the app.js (the control for the page for the image viewer:
var app = angular.module('app', ['angular-flexslider']);
app.controller('MainCtrl', function ($scope) {
var ctrl = this;
$scope.prod = { imagePaths: [] };
$scope.prod.imagePaths = [
{ custom: 'http://flexslider.woothemes.com/images/kitchen_adventurer_cheesecake_brownie.jpg', thumbnail: 'http://flexslider.woothemes.com/images/kitchen_adventurer_cheesecake_brownie.jpg' },
{ custom: 'http://flexslider.woothemes.com/images/kitchen_adventurer_lemon.jpg', thumbnail: 'http://flexslider.woothemes.com/images/kitchen_adventurer_lemon.jpg' },
{ custom: 'http://flexslider.woothemes.com/images/kitchen_adventurer_donut.jpg', thumbnail: 'http://flexslider.woothemes.com/images/kitchen_adventurer_donut.jpg' },
{ custom: 'http://flexslider.woothemes.com/images/kitchen_adventurer_caramel.jpg', thumbnail: 'http://flexslider.woothemes.com/images/kitchen_adventurer_caramel.jpg' },
{ custom: 'http://flexslider.woothemes.com/images/kitchen_adventurer_cheesecake_brownie.jpg', thumbnail: 'http://flexslider.woothemes.com/images/kitchen_adventurer_cheesecake_brownie.jpg' },
{ custom: 'http://flexslider.woothemes.com/images/kitchen_adventurer_lemon.jpg', thumbnail: 'http://flexslider.woothemes.com/images/kitchen_adventurer_lemon.jpg' },
{ custom: 'http://flexslider.woothemes.com/images/kitchen_adventurer_donut.jpg', thumbnail: 'http://flexslider.woothemes.com/images/kitchen_adventurer_donut.jpg' },
{ custom: 'http://flexslider.woothemes.com/images/kitchen_adventurer_caramel.jpg', thumbnail: 'http://flexslider.woothemes.com/images/kitchen_adventurer_caramel.jpg' },
{ custom: 'http://flexslider.woothemes.com/images/kitchen_adventurer_cheesecake_brownie.jpg', thumbnail: 'http://flexslider.woothemes.com/images/kitchen_adventurer_cheesecake_brownie.jpg' },
{ custom: 'http://flexslider.woothemes.com/images/kitchen_adventurer_lemon.jpg', thumbnail: 'http://flexslider.woothemes.com/images/kitchen_adventurer_lemon.jpg' },
{ custom: 'http://flexslider.woothemes.com/images/kitchen_adventurer_donut.jpg', thumbnail: 'http://flexslider.woothemes.com/images/kitchen_adventurer_donut.jpg' },
{ custom: 'http://flexslider.woothemes.com/images/kitchen_adventurer_caramel.jpg', thumbnail: 'http://flexslider.woothemes.com/images/kitchen_adventurer_caramel.jpg' }
];
});
Finally the partial for the image viewer/gallery page
<div id="container" ng-controller="MainCtrl">
<div class="col-sm-12">
<flex-slider slider-id="slider" flex-slide="image in prod.imagePaths track by $index" animation="fade" animation-loop="false" sync="#carousel" slideshow="false" control-nav="false" init-delay="100">
<li>
<img ng-src="{{image.custom}}">
</li>
</flex-slider>
</div>
<div class="col-sm-12">
<flex-slider slider-id="carousel" flex-slide="image in prod.imagePaths track by $index" animation="slide" animation-loop="false" item-width="210" item-margin="5" as-nav-for="#slider" slideshow="false" control-nav="false">
<li>
<img ng-src="{{image.thumbnail}}">
</li>
</flex-slider>
</div>
</div>
You have to inject all of your modules in a single call, so you would use:
var app = angular.module('app', ['ngRoute','angular-flexslider']);
The way you are currently doing it your module is destroy when add the second module to it.

How to get AngularJS routing to maintain state?

I'm getting up to speed with AngularJS routing and have created this example which works.
However, I understood that if on page "home" I type in a text into the input box, then click on page "about" and then come back to "home", the text would still be in the input box, i.e. would have maintained the state.
Is this not the case, and if not, is there a way to maintain state in forms on pages which the user navigates away from?
home.htm
<div class="jumbotron">
<h1>Home</h1>
<p>{{subtitle}}</p>
</div>
<input ng-model="message"/>
index.htm
<html ng-app="mainApp">
<head>
<script src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular-route.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
<link href="http://netdna.bootstrapcdn.com/font-awesome/4.0.0/css/font-awesome.css" rel="stylesheet" />
<style type="text/css">
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
}
a:focus {
outline: none;
}
</style>
</head>
<body ng-cloak ng-controller="mainController">
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<div class="navbar-brand">AngularJS Routing</div>
</div>
<div>
<ul class="nav navbar-nav">
<li><i class="fa fa-home"></i> Home</li>
<li><i class="fa fa-shield"></i> About</li>
<li><i class="fa fa-comment"></i> Contact</li>
</ul>
</div>
</div>
</nav>
<div class="col-lg-12">
<div ng-view></div>
</div>
<script>
var mainApp = angular.module('mainApp', ['ngRoute']);
mainApp.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'pages/home.htm',
controller: 'mainController'
})
.when('/about', {
templateUrl: 'pages/about.htm',
controller: 'aboutController'
})
.when('/contact', {
templateUrl: 'pages/contact.htm',
controller: 'contactController'
})
.otherwise({
redirectTo: '/'
});
});
mainApp.controller('mainController', function ($scope) {
$scope.subtitle = 'the home page';
$scope.message = '';
});
mainApp.controller('aboutController', function ($scope) {
$scope.subtitle = 'the about page';
});
mainApp.controller('contactController', function ($scope) {
$scope.subtitle = 'the contact page';
});
</script>
</body>
</html>
Controllers do not maintain state, they are created and destroyed every time you go through the route. You will need to implement a service that you can use to store your data and then have a means to send the data to the service when you want to persist it. Controller have a '$destroy' event that occurs right before the scope is released that you can hook.
mainApp.service('myData', function() {
this.message = '';
})
.controller('mainController', function($scope, myData) {
$scope.message = myData.message;
$scope.$on("$destroy", function() {
myData.message = $scope.message;
});
});

ui-router dots in name not working

The UI-Router docs shows that you can use dots in route name:
<!-- partials/state1.html -->
<h1>State 1</h1>
<hr/>
<a ui-sref="state1.list">Show List</a>
<div ui-view></div>
But however in my app this doesn't work. This is an example that worked fine until I changed client to client.ts everywhere:
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<title>AngularJS: UI-Router Quick Start</title>
<!-- Bootstrap CSS -->
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="container">
<div class="navbar">
<div class="navbar-inner">
<a class="brand" ui-sref="index">Quick Start</a>
<ul class="nav">
<li><a ui-sref="index">Home</a></li>
<li><a ui-sref="clien.ts">Clients</a></li>
<li><a ui-sref="route1">Route 1</a></li>
</ul>
</div>
</div>
<div class="row">
<div class="span6">
<div class="well" ui-view=""></div>
</div>
<div class="span6">
<div class="well" ui-view="viewB"></div>
</div>
</div>
<!-- Angular -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.4/angular.min.js"></script>
<!-- UI-Router -->
<script src="//angular-ui.github.io/ui-router/release/angular-ui-router.js"></script>
<!-- App Script -->
<script>
var myapp = angular.module('myapp', ["ui.router"])
myapp.config(function($stateProvider){
$stateProvider
.state('index', {
url: "",
views: {
"": {
template: "index.viewA-index"
},
"viewB": {
template: "index.viewB"
}
}
})
.state('route1', {
url: "/route1",
views: {
"": {
template: "route1.viewA-route1"
},
"viewB": {
template: "route1.viewB"
}
}
})
.state('clien.ts', {
url: "/clients",
views: {
"viewB": {
template: "clients.viewA-route2"
},
"": {
controller: function($scope, ClientService) {
console.log('Controller code being run');
$scope.clients = ClientService.clientList();
},
templateUrl: 'client-list-template.html'
}
}
})
})
.service('ClientService', function() {
this.clientList = function() {
clients = [{'name': 'Acme Food', 'description': 'Makers of fine food'},
{'name': 'Dog Biscuits Inc', 'description': 'Cruncy creations for canines'},
{'name': 'Parrot treats Ltd', 'description': 'Puveyors of bird food'},
{'name': 'Pond supplies', 'description': 'Sell fish and gravel'}];
return(clients);
}
});
</script>
</body>
</html>
Plunker here: http://plnkr.co/edit/ZD7WlC9aKzpwte9dVMxC?p=preview
As you can see the link can't be clicked :/
What you need to do is add an abstract state for clien in that case.
Here's the plunkr, with the added state: plunkr
Whenever you define states with the dot. You still need to at least define the abstract state for the child. In your case for clien.
Also something from the docs
If you register only a single state, like contacts.list, you MUST define a state called contacts at some point, or else no states will be registered. The state contacts.list will get queued until contacts is defined. You will not see any errors if you do this, so be careful that you define the parent in order for the child to get properly registered.

Resources