ui-sref is not working properly - angularjs

ui-sref in my application is working partially. Mean for some link it is generating href but for other's not. below is my code:-
// for ng-repeat it is not working but for others it is working.
<nav class="site-links" ng-controller="itemsController">
<ul class="nav-links">
<li ng-repeat="item in items">
<a ui-sref="{{item.link}}">
<span>{{item.Description}}</span>
</a>
</li>
<li><a ui-sref="index">Home</a></li>
<li><a ui-sref="route1">Route 1</a></li>
<li><a ui-sref="route2">Route 2</a></li>
</ul>
Could you take a look??

Provided you have the following routes defined in you router:
$stateProvider
.state( 'testState', {
url: '/test',
templateUrl: 'app/templates/test.html',
controller: 'testController'
});
You can link to this state via the ui-sref directive ONLY by its name. So, the following is valid:
<a ui-sref="testState">Something</a>
Something <!-- Notice the difference. Here we're using the reference to the route. -->
So, for the ui-sref you need to tell it the NAME of the state and for the normal href, a simple route is fine.

Related

Angular ui-router nested states without nested views

Let's say I have a films app. It has Home/About/Films pages. Films page has subcategories: Comedy/Drama. Currently, I'm struggling with navigation. The Goal is when I click Home - it should render home. About - about. Films - render all films (for example simple cards with title/genre/year). When I click Films->Comedy - it should use the same controller as Films, render exactly same template but only comedy films. Moreover, navigation should be active with Films and Comedy.
I've created plunker to demonstrate first approach https://plnkr.co/edit/d0Db18ZJYtQx6aJEZ3xa?p=preview
So my first approach was:
.state('layout.films', {
url: '/films',
controller: 'FilmsCtrl as films',
template: '<div>All films</div>'
})
.state('layout.films.genre', {
url: '/:genre',
controller: 'FilmsCtrl as films',
template: '<div>{{ films.genre }} films</div>'
})
and this layout:
<div class="layout">
<ul>
<li><a ui-sref-active="_active" ui-sref="layout.home">home</a></li>
<li><a ui-sref-active="_active" ui-sref="layout.about">about</a></li>
<li>
<a ui-sref-active="_active" ui-sref="layout.films">films</a>
<ul>
<li><a ui-sref-active="_active" ui-sref="layout.films.genre({genre: 'comedy'})">comedy</a></li>
<li><a ui-sref-active="_active" ui-sref="layout.films.genre({genre: 'drama'})">drama</a></li>
</ul>
</li>
</ul>
<hr>
<div ui-view></div>
</div>
But that doesn't work. Turns out to be that nested states requires nested views. I was sad. And tried second approach: https://plnkr.co/edit/3YWAoLcPU3fd2FdebWpD?p=preview
I created only one films state:
.state('layout.films-genre', {
url: '/films/:genre?',
controller: 'FilmsCtrl as films',
template: '<div>{{ films.genre }} films</div>'
})
And fixed layout to work with this:
<a ui-sref-active="_active" ui-sref="layout.films-genre">films</a>
<ul>
<li><a ui-sref-active="_active" ui-sref="layout.films-genre({genre: 'comedy'})">comedy</a></li>
<li><a ui-sref-active="_active" ui-sref="layout.films-genre({genre: 'drama'})">drama</a></li>
</ul>
Seems working. It even highlights menu items properly (wow). But actually... I can't change state from films->comedy to films. Next thought was to change the link to the all films:
<a ui-sref-active="_active" ui-sref="layout.films-genre({genre: ''})">films</a>
But now it doesn't highlight root menu item (films) when I click one of the genres. What should I do to implement desired behavior?
If I understand your question correctly, you want to have a page that can render a specific genre of films?
If so, I think you should look up stateParams. This way you could have a menu that all directs to the same child view, but sends different parameters. Then sort the list of movies accordingly to the params being sent.
It would look something like this:
.state('layout.films-genre', {
url: '/films',
controller: 'FilmsCtrl as films',
template: '<div> Template goes here </div>'
params: { genre: 'all' } // as default if I remember correctly
})
You might aswell find the answer to your question here:
How to pass parameters using ui-sref in ui-router to controller

Showing HTML Elements based on current Angular Route

I am trying to add three additional list items based on the routeProvider. If the reports route is navigated to, I want to use ng-show to make three more list items visible. I want them to remain visible unless the create user or manage user route is navigated to. The new list items are access reports and details reports.
HTML:
<ul class="nav nav-pills nav-stacked">
<li>
Create User
</li>
<li>
Manage Users
</li>
<li>
Reports
</li>
</ul>
routeProvider.js
adminApp.config(function($routeProvider) {
$routeProvider
.when('/createUser', {
templateUrl : 'app/components/admin/views/createUserView.html',
controller : 'createUserController'
})
.when('/manageUsers', {
templateUrl : 'app/components/admin/views/manageUsersView.html',
controller : 'manageUsersController'
})
.when('/editUser', {
templateUrl : 'app/components/admin/views/editUserView.html',
controller : 'manageUsersController'
})
.when('/reports', {
templateUrl : 'app/components/admin/views/reportsView.html',
controller : 'reportsController'
})
.when('/reports', {
templateUrl : 'app/components/admin/views/accessReportsView.html',
controller : 'reportsController'
})
.when('/reports', {
templateUrl : 'app/components/admin/views/detailsReportView.html',
controller : 'reportsController'
})
I am trying to do something like this:
<ul class="nav nav-pills nav-stacked">
<li>
Create User
</li>
<li>
Manage Users
</li>
<li>
Reports
</li>
<!--show this list item if the route is /reportsView or /accessReportsView orsummaryReportsView-->
<li>
<a ng-show="" href="#reports"> Access Reports</a>
</li>
</ul>
Link git repo if needed
Seems like as per you current configuration you should have #/ in your anchors href attribute
<ul class="nav nav-pills nav-stacked">
<li>
Create User
</li>
<li>
Manage Users
</li>
<li>
Reports
</li>
</ul>

UI Router - Set parent to active for all child states when ui-sref is given as link to one child

Hi I have created a AngularJS application. I'm using UI-router.
I have one main menu and then sub menu.
Main menu I have something like
<ul class="nav nav-pills">
<li ng-class="{'active':$state.includes('home')}"><a ui-sref="home.main1">Home</a></li>
<li ui-sref-active="active"><a ui-sref="dashboard.dash1">Dashboard</a></li>
<li ui-sref-active="active"><a ui-sref="report">Reports</a></li>
</ul>
For one main menu home I have sub menu as
<ul class="nav nav-tabs" role="tablist">
<li ui-sref-active="active"><a ui-sref="home.main1">Main 1</a></li>
<li ui-sref-active="active"><a ui-sref="home.main2">Main 2</a></li>
</ul>
And for main menu dashboard i have sub menu as
<ul class="nav nav-tabs" role="tablist">
<li ui-sref-active="active"><a ui-sref="dashboard.dash1">Dashboard 1</a></li>
<li ui-sref-active="active"><a ui-sref="dashboard.dash2">Dashboard 2</a></li>
</ul>
In the above, the sub menus becomes active as per URL. but the parent menu is not becoming active.
In dashboard, I set ui-sref-active but the problem is the ui-sref**I set to **dash1 state. So dashboard state becomes active only when dash1 is active, not dash2.
In home I tried using ng-class as you can see. But it's not working.
Here is the plnkr Demo.
How to set the parent state active whenever child is active?
<li ng-class="{'active':$state.includes('home')}">
The expression you're using with ng-class above is evaluated in the context of the current $scope. Your controller doesn't define anything on the $scope, so the expression fails.
You can do this to make it work (plunkr):
app.controller('testCtrl', function($scope, $state) {
console.log($state.current.name);
$scope.$state = $state;
});
The merits of putting a service on the scope are debatable.

multiple nested views with their own router

I am building an angular app with nested views using ui-router. The app has a list of posts, each with its own Nav menu to change the post's view.
To simplify the context, lets just say that each nav menu can change the theme of the post it is attached to.
POST 1 CONTENT
[Light theme button] [Dark theme button]
--------------------------------------------
POST 2 CONTENT
[Light theme button] [Dark theme button]
--------------------------------------------
*
*
*
The problem I am facing is when I press a button on one post's nav menu, all the posts change.
I want the nav menu for each post only to effect its respective post.
I am a total beginner to angular and my questions are:
Is this a problem i would want to solve with ui-router? (do i want to
have a router for each post?)
If it is, how do i solve it?
If not, can you point me in the right direction?
any help is appreciated, whether it is a link, explanation, code or just a comment.
PS. in reality i am not just changing the theme, i am changing the content on the post completely. In the future i want to implement more than just 2 options menu options.
here is the code that i am using now (modified a bit to remove redundancy):
Main.js:
angular.module('app',['ui.router'])
.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/postlist');
$stateProvider
.state('postlist', {
url: '/postlist',
templateUrl: 'ListView.html',
controller: ListCtrl
})
.state('postlist.light', {
templateUrl: 'pollViewLight.html',
controller: PollLightCtrl
})
.state('postlist.dark', {
templateUrl: 'pollViewDark.html',
controller: PollDarkCtrl
})
});
simplified part of index.html:
<nav>
<ul>
<li><a ui-sref="postlist">Post List</a></li>
</ul>
</nav>
<div class="container">
<div ui-view></div>
</div>
ListView.html:
<div class="row" ng-repeat="post in posts">
<div class="col">
<div ui-view></div>
<ul class="nav nav-pills">
<li><a ui-sref=".light">Light Theme</a></li>
<li><a ui-sref=".dark">Dark Theme</a></li>
</ul>
</div>
</div>

angular-ui-router dynamic menu: TypeError: Cannot call method 'match' of undefined while rendering menu

i am new to angular and angular-ui-router and trying to create a menu.
I tried angular-ui-router and think that it fits for my needs.
now i have a problem while creating the menu with the ui-router attributes.
my html code looks like that:
<div ng-controller="MenuCtrl">
<ul>
<li ng-repeat="item in menu">
<a ui-sref="cf.{{item}}">{{item}}</a>
</li>
</ul>
</div>
the menu array contains different entries dependent on the info if the user is logged in.
now i get this error message:
TypeError: Cannot call method 'match' of undefined
<a ui-sref="cf.{{item}}" class="ng-binding">
It looks like ui-router tries to get access to the list entry before it is rendered complete with ng-repeat.
What can i do to prevent this problem?
So ui-router doesn't support interpolation in ui-sref, believe me I wish they would. Here is how I solved this.
In your controller:
app.controller("MenuCtrl", ['$scope', '$state', function($scope, $state) {
$scope.$state = $state;
}]);
In your view use an ng-href to evaluate $state object that we've now added to the $scope:
<div ng-controller="MenuCtrl">
<ul>
<li ng-repeat="item in menu">
<a ng-href={{ $state.href('cf.' + item) }}>{{item}}</a>
</li>
</ul>
</div>
You can also you this technique for wildcard params:
ng-href="{{ $state.href('cf.items.item', {'item' : item} ) }}"
Assuming you've set up your ui-router routes properly for this.

Resources