I'l try to use AngularJs with ui.router, but have the trouble.
This example have three states: index, template and template.show
$stateProvider
.state('/', {
url: '',
template: '<a ui-sref="template">GoTo Template Index</a>'
})
.state('template', {
url: 'template',
templateUrl: 'template_index.html',
controller: 'TemplateCtrl'
})
.state('template.show', {
url: '/{templateId:[0-9]+}',
templateUrl: 'template_show.html',
controller: 'TemplateShowCtrl'
})
Please, see plunker: http://plnkr.co/edit/prluQs9vXeJw9IVi2JYW?p=info
But only two first states working. State "template.show" changing, loading template, but does not execute TemplateShowCtrl and not update ui-view to new template.
You can see screenshot
Any child state requires the presence of a subsequent ui-view directive in its parent so that it knows where to insert the html. Currently, there is not one present in the template_index.html markup.
It should instead look something akin to this:
<ul>
<li ng-repeat="t in templates">
<a ui-sref="template.show({templateId:t.id})" href='#'>
{{t.name}}
</a>
</li>
</ul>
<!-- target element -->
<ui-view></ui-view>
Related
I'm using Angular ui route and I'm trying to pass query parameters but it doesn't work. I have followed the official wiki.
In the view I have the following code very simple
<div ng-controller="MainController">
<a ng-href="#/foo/bar?param={{make}}"><li>{{make}}</li></a>
</div>
and this is the config
function config($stateProvider, $urlRouterProvider) {
$stateProvider
.state('foo', {
url: '/foo',
templateUrl: '/partials/foo.html',
controller: 'MainController'
})
.state('foo.bar', {
url: '/bar?param',
templateUrl: 'partials/foo.bar.html',
controller: 'SecondaryController'
});
}
but when I click on the link in the view the url I get it is what I get but the route doesn't receive the request.
Use ui-sref directive to generate href link
Markup
<div ng-controller="MainController">
<a ui-sref="foo.bar({param: make})"><li>{{make}}</li></a>
</div>
I have the following code in my app.js:
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'app/login/login.html'
})
.state('admin', {
url: '/admin',
templateUrl: 'app/admin/layout/layout.html',
abstract: true
})
.state('admin.dashboard', {
url: '',
templateUrl: 'app/admin/dashboard/dashboard.html'
})
.state('admin.client', {
url: '/client',
templateUrl: 'app/admin/client/client.html',
controller: 'ClientController',
})
.state('admin.client.new', {
url: '/client/new',
templateUrl: 'app/admin/client/new.html',
controller: 'ClientController',
})
Then, on layout.html I have this:
<section class="content" ui-view></section>
Which loads the admin.dashboard by default. And from there I have a link to load the admin.client
It's fine. But the problem comes in my client.html. I got the following:
<a ui-sref=".new">
<button class="btn btn-app">
<i class="ion ion-plus"></i> New Client
</button>
</a>
What I expect it to do is to change the ui-view in layout.html from client/client.html to client/new.html but nothing happens.
If I add an ui-view tag inside client.html then the new.html is loaded there. But I need it to load on ui-view of layout.html.
If you use the attribute ui-view without specifying view name like ui-view="myviewname", stateProvider is matching the view hierarchy (the nested ui-view attributes) to your state hierarchy. So its expecting to find the target ui-view in client.html, like you found out yourself.
Change the state name 'admin.client.new' to 'admin.newclient', and your ui-sref link to 'admin.newclient'. Maybe that's what you want.
StrangeLoop's answer worked but I found a better solution.
I added the parent parameter to the new client state. Now it looks like:
.state('admin.client.new', {
parent: 'admin',
url: '/client/new',
templateUrl: 'app/admin/client/new.html',
controller: 'ClientController',
})
And on client.html:
<a ui-sref="admin.client.new">
<button class="btn btn-app">
<i class="ion ion-plus"></i> Novo Cliente
</button>
</a>
I'm using AngularUI Router and I'm trying to have nested/children links.
All works fine but how do I have selected/active link in Contact tab?
Basically, I need to be able to have selected/active contact one link when the Contact page is loaded. Currently it does not read for some reason the controlleroneCtrl unless I click on the link contact one.
angular
.module ('myApp', ['ui.router'
])
.config (['$urlRouterProvider', '$stateProvider', function ($urlRouterProvider, $stateProvider) {
$urlRouterProvider.otherwise ('/summary');
$stateProvider.
state ('summary', {
url: '/summary',
templateUrl: 'summary.html',
controller: 'summaryCtrl'
}).
state ('about', {
url: '/about',
templateUrl: 'about.html',
controller: 'aboutCtrl'
}).
state ('contact', {
url: '/contact',
templateUrl: 'contact.html',
controller: 'contactoneCtrl'
})
// Sub page
.state('contact.one',{
url: '/contact.contactone',
templateUrl: 'one.html',
controller: 'contactoneCtrl'
})
// Sub page
.state('contact.two',{
url: '/contact.contacttwo',
templateUrl: 'two.html',
controller: 'contacttwoCtrl'
});
}]);
Plunker: http://plnkr.co/edit/DWjp5M6kJt2MyBrasfaQ?p=preview
There's a much quicker way to do this. Just use the ui-sref-active="active" attribute instead of ui-sref.
An example:
<ul>
<li ui-sref-active="active">
<a ui-sref="state">State 1</a>
<li>
<ul>
When the state is active the list item gets the class active. If you want a different class for active states or more than one class, just add it as follows
<ul>
<li ui-sref-active="active so-active super-active">
<a ui-sref="state">State 1</a>
<li>
<ul>
I use the pattern of exposing state on the root scope and using state.current.name in templates. I justify this global exposure because it's an app-level concern. If your navigation directive has isolate scope you'll need to pass it in, but that's no biggie.
In practice it's been very good for us I think.
Looks like this:
javascript
app = angular.module ('myApp', ['ui.router']);
app.controller('MainController', function($scope, $state){
$scope.state = $state;
});
html:
<nav>
<ul>
<li ng-repeat="tab in tabs" ng-class="{active: state.current.name === tab.id}>{{tab.name}}</li>
</ul>
</nav>
here is the updated plunk - http://plnkr.co/edit/UjjNm4JJIsjb4ydWZRDi?p=preview
Changes
added a new controller contactCtrl
setup $state.go('contact.contactone'); inside the contactCtrl
updated app.js so that /contact points to contactCtrl
I'm using ng-class like this:
ng-class="{active: state.current.name.split('.')[1] === 'homepage'}"
My "state" name is structured like:
app
app.homepage
app.profile
app.profile.user
.etc
For example, in my homepage, it's button became like this:
<li ng-class="{active: state.current.name.split('.')[1] === 'homepage'}"><a ui-sref="app.homepage">Home</a></li>
So just define scope of $state like #Simple As Could Be said at root of the app controllers, and you can use ng-class to whatever your app's state and how deep your app's state nested.
See my plunk http://embed.plnkr.co/bRfl1S9KXQuvL0Bvt9jD/preview.
Also try updating the version of ui-router to 0.2.12.
Only client tab as really been implemented.
I'm working on a project that has implemented the UI router and it's using ui-sref-active="active" to add the active class to the navigation menu item when that item is the current route. However, when you navigate to a nested view within that view, the parent menu item is no longer active. See the following Plunker:
http://plnkr.co/edit/2CoEdS?p=preview
By default (or if you click on it) Route 1 is "active". When you click on "Show List," you will see that Route 1 is no longer active.
Edit:
The only difference between this example and my actual project is that the navigation menu in my actual project has its own controller and so does not use the same scope as the controller for "route1".
EDIT For updated ui-router 0.2.13:
ui-sref-active="active" now sets the 'active' class when the current state is the ui-sref's state or any child
ui-sref-active-eq="active" behaves as the previous iterations of ui-sref-active, and only sets the class for the exact state
Original Answer:
See open ui-router issues:
https://github.com/angular-ui/ui-router/issues/704 and 818
A general workaround people are suggesting is:
ng-class="{active:$state.includes('route1')}"
Of course, $state must be added to $scope. See updated plunk: http://plnkr.co/edit/KHLDJP?p=preview
You are having a wrong understanding of ui-sref-active="active"
<li ui-sref-active="active"><a ui-sref="route1">Route 1</a></li>
This will show special css highlighting only when you are in state route1 (reference https://github.com/angular-ui/ui-router/wiki/Quick-Reference#wiki-ui-sref-active). This is the case when you click on route 1. But when you click on "Show list" you are no longer in route1.
Rather you are in state "route1.list" . You can verify this by writing the following code. This is strictly for understanding how state works.
js
inside controller
$rootScope.currentState = $state.$current.name //using rootScope so that you can access the variable anywhere inside html
inside html
{{currentState}}
If you look closely at documentation of ui-sref-active, it not only looks at stateName but also stateParams, hence when you go to substate it no longer changes css. From the sourcecode it becomes clearer.
function update() {
if ($state.$current.self === state && matchesParams()) {
$element.addClass(activeClass);
} else {
$element.removeClass(activeClass);
}// route1===route1.list will not be true.
to solve the problem, remember scope variables are inherited in nested views.
inside controller of route.
$scope.route1Active = true;
in html
<li ng-class={active:route1Active}><a ui-sref="route1">Route 1</a></li>
Angular UI router now supports this natively. See commit https://github.com/angular-ui/ui-router/commit/bf163ad6ce176ce28792696c8302d7cdf5c05a01
My solution was to set:
<li ng-class="{ 'active': state.current.name.indexOf('route1') != -1 }">
The state was already previously added to the controller's scope:
$scope.state = $state;
You do not need to do any thing in the controllers. Here is my example code:
<ul class="nav nav-pills nav-stacked" role="tablist">
<li ui-sref-active="active"><a ui-sref="Booking.Step1" href="#/Booking/Step1">Step1</a></li>
<li ui-sref-active="active"><a ui-sref="Booking.Step2" href="#/Booking/Step2" >Step2</a></li>
<li ui-sref-active="active"><a ui-sref="Booking.Step3" href="#/Booking/Step3">Step3</a></li>
<li ui-sref-active="active"><a ui-sref="Booking.Step4" href="#/Booking/Step4">Step4</a></li>
<li ui-sref-active="active"><a ui-sref="Booking.Step5" href="#/Booking/Step5">Step5</a></li>
</ul>
In route configuration:
$stateProvider.state('Booking', {
abstract: true,
url: '/Booking',
templateUrl: "TourApp/Templates/Booking/SideMenu.html",
controller: "SideMenuController"
});
$stateProvider.state('Booking.Step1', {
url: "/Step1",
views: {
'content': {
templateUrl: "TourApp/Templates/Booking/Step1.html",
controller: "Step1Controller"
}
}
});
$stateProvider.state('Booking.Step2', {
url: "/Step2",
views: {
'content': {
templateUrl: "TourApp/Templates/Booking/Step2.html",
controller: "Step2Controller"
}
}
});
Now they have updated and the new way to do that is
<a ui-sref-active="{'active': 'main.app.manage.**'}" ui-sref="main.app.manage.people.list"></a>
Below is the state file
angular.module('manage.people', ['people.invite'])
.config(['$stateProvider', function($stateProvider) {
$stateProvider
.state('main.app.manage.people', {
url: '/people',
abstract: true,
cache: false,
views: {
'tabContent': {
template: '<div ui-view="peopleContent"></div>',
controller: 'peopleController'
}
}
})
.state('main.app.manage.people.list', {
url: '/list',
views: {
'peopleContent': {
templateUrl: '/internal/main/app/manage/people/views/people.html',
controller: 'peopleListController'
}
}
});
We already have a solution without any "hack" HERE
That's the way to do:
HTML >
<li ui-sref-active="active" >
<a href="#" class="submenu" ui-sref="bands">
<i class="fa fa-location-arrow" aria-hidden="true"></i>
Bands
<span class="fa fa-chevron-down"></span>
</a>
<ul class="nav child_menu">
<li ui-sref-active="active">
<a ui-sref="bands.nirvana">
Nirvana
</a>
</li>
<li ui-sref-active="active">
<a ui-sref="bands.iron">
Iron
</a>
</li>
<li ui-sref-active="active">
<a ui-sref="bands.metalica">
Metalica
</a>
</li>
</ul>
Our router config will be like this >
$stateProvider.state('bands', {
abstract: true,
url: '/bands',
templateUrl: "myapp/categories/template.bands.html", //<ui-view></ui-view>
controller: "SomeController as vm"
}).state('bands.nirvana', {
url: '/nirvana',
templateUrl: "myapp/categories/band.nirvana.html",
controller: "SomeController as vm"
}).state('bands.iron', {
url: '/iron',
templateUrl: "myapp/categories/band.iron.html",
controller: "SomeController as vm"
}).state('bands.meatlica', {
url: '/metalica',
templateUrl: "myapp/categories/band.metalica.html",
controller: "SomeController as vm"
})
I have come here 2 years later the question was asked but angular-ui-router has much proficient approach in solving this issue. It worked for nested states too.
<ul>
<li ui-sref-active="active" class="item">
<a ui-sref="home">Home</a>
</li>
<!-- ... -->
</ul>
When app navigates to home state, this is how resulting HTML will appear :
<ul>
<li ui-sref-active="active" class="item active">
<a ui-sref="home">Home</a>
</li>
<!-- ... -->
</ul>
ui-sref-active quick reference :
A directive working alongside ui-sref to add classes to an element
when the related ui-sref directive's state is active, and removing
them when it is inactive. The primary use-case is to simplify the
special appearance of navigation menus relying on ui-sref, by having
the "active" state's menu button appear different, distinguishing it
from the inactive menu items.
Complete documentation.
I hope this is what you have been looking for.Place the parent url in the list class ,now whenever you navigate to child class parent class will be active
Step 1: Add a Controller for your nav bar orin your existing controller where nav bar is included add the following
app.controller('navCtrl', ['$scope', '$location', function($scope, $location) {
$scope.isActive = function(destination) {
return destination === $location.path();
}
}]);
Step2: In your nav bar
<li ng-class="{active: isActive('/home')}"><a ui-sref="app.home">Browse Journal</a></li>
Thats it.
I'm setting up a very simple AngularJS application and am running into a minor, yet frustrating, issue. Here is the sample application using $routeProvider:
angular.module('thought', [], function($routeProvider, $locationProvider) {
$routeProvider.
when('/thought', {
templateUrl: 'partials/thought/posts.html',
controller: ThoughtCntl
}).
when('/thought/edit/:id', {
templateUrl: 'partials/thought/edit.html',
controller: EditCntl
}).otherwise({
redirectTo: '/thought'
});
$locationProvider.html5Mode(true);
});
Here is the content of posts.html:
<div>
<button>Create</button>
<div>
<h3>Posts</h3>
<ul>
<li ng-repeat="post in publishedPosts">
{{post.title}}
</li>
</ul>
</div>
</div>
When I navigate to /thought, posts.html loads with the appropriate data content. The the link contains 'href=localhost:8080/thought/edit/1234' as it should. However, when I click the link, it attempts to load the template from 'localhost:8080/thought/edit/partials/thought/edit.html'. The templateUrl path is appended to the href path. I'm sure that something simple is mis-configured, but I can't find it. Any ideas what I should look at?
Thanks!
Use the <base> tag :
<base href="/" />