I have the below states, they appear in a menu which has a submenu.
What I would like to do is, when I click on the first state ('app.web'), to have in the menu both buttons 'active' (I use ui-sref-active="active" on main and sub menu <li>) and when I click on the second state, to have again both buttons 'active'.
At the moment, the below setup is
not working if I click the main menu, but
is working when I click the sub menu button.
main menu link state:
.state('app.web', {
url: '/:webID/dashboard',
views: {
'container#': {
templateUrl: '...',
}
}
sub menu link state:
.state('app.web.dashboard', {
url: '^/:webID/dashboard',
views: {
'container#': {
templateUrl: '...',
controller: '...',
}
}
}
I understand you want to have both links to be marked with "active" ... parent and child ... even if only parent is selected. But this is not possible...
As we can read here:
ui-sref-active
Description
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.
...
Will activate when the ui-sref's target state or any child state is active...
As shown in the doc (cited above): "Will activate when the ui-sref's target state or any child state is active".
Other words, having selected Parent - will never trigger that feature.
Here is a working plunker showing how these links will be decorated:
<a ui-sref-active="active" ui-sref="app">
<a ui-sref-active="active" ui-sref="app.web({webID:123})">
<a ui-sref-active="active" ui-sref="app.web.dashboard({webID:123})">
EXTEND: why is this plunker not working?
// working
<a ui-sref-active="current" ui-sref="home">
<a ui-sref-active="current" ui-sref="home.child1">
<a ui-sref-active="current" ui-sref="home.child2">
// NOT WORKING
<a ui-sref-active="current" href="#/home">
<a ui-sref-active="current" href="#/home/child1">
<a ui-sref-active="current" href="#/home/child2">
The point is - ui-sref-active is dependent on ui-sref. The above doc link says:
ui-sref-active can live on the same element as ui-sref or on a parent element. The first ui-sref-active found at the same level or above the ui-sref will be used.
The point is - we need ui-sref. Without that directive, the ui-sref-active simply won't work.
Some more details could be found in this answer
Related
We have a series of notifications and want to make the overall item clickable to the related item. This has been implemented using ui-sref and functions correctly. However, within that, there are to be a series of nested links that go to other relevant information. The problem at the moment is this parent ui-sref overrides all of these links. I've tried implementing these nested links as standard anchor and ui-sref but it has the same effect. So the hyperlink shows correctly, and when clicking on it, it goes to it for a split second, then reverts back to the ui-sref link.
Here is a code example:
<div class="NotificationItemBalanced">
<div class="notificationItem" ui-sref="community.act({slug: slug, id: id})">
<div class="messageBodyWrapper">
<span class="messageText"><strong><a ui-sref="user.posts({username: username})"></a></strong> commented on your post</span>
</div>
</div>
</div>
Is this related to the ui-sref or is there a specific setting in the routes to fix this?
Thanks
Just create a directive like:
myApp.directive('preventBubbling', function() {
return {
link: function($scope, element) {
element.on("click", function(e) {
e.stopPropagation();
});
}
};
});
And add it to your inner links:
<a ui-sref="user.posts({username: username})" prevent-bubbling></a>
Basically, when you click on a nested element, the click event bubbles up to the DOM tree. So we are simply stopping it to propagate.
https://developer.mozilla.org/en/docs/Web/API/Event/stopPropagation
Update
Also, if your inner links are inheriting properties from parent ui-sref then you should use ui-sref-opts as well:
<a ui-sref="user.posts({username: username})" ui-sref-opts="{inherit: false}" prevent-bubbling></a>
I am using ui-sref for routing depending upon state.
Currently I am getting child's view inside parent as hierarchy. I want to assign a child's view to a parent view. Current state is as below plunker.
[link][//plnkr.co/edit/fpsTWglicbcGMotJIlll]
I want to see welcome after clicking click me.
If I understood your question correctly, the problem is you have inner as a child of tab1... so it is displayed in the ui-view of tab1. If you want it instead to make it replace tab1, then you don't need the ui-view in tab1.
Here's a forked plunker showing what I mean.
http://plnkr.co/edit/t4cxejVLGf4kywKp2bb5?p=preview
The parts I changed:
.state("main", { abtract: true, url:"/main", templateUrl:"main.html" })
.state("main.tab1", { url: "/tab1", templateUrl: "tab1.html" })
.state("main.inner",{
url:"/inner",
templateUrl:"inner.html"
})
.state("main.tab2", { url: "/tab2", templateUrl: "tab2.html" })
And in tab1.html
<div>
This is the view for tab1
<a ui-sref="main.inner">click me</a>
</div>
Is this what you're shooting for?
Add $scope.$state = $state;in the controller.
Then add ng-hide="$state.current.name === 'main.tab1.inner'" to
<h2 ng-hide="$state.current.name === 'main.tab1.inner'">View:</h2>
and
<div ng-hide="$state.current.name === 'main.tab1.inner'">
This is the view for tab1
<a ui-sref="main.tab1.inner">click me</a>
</div>
Here's the link [link] http://plnkr.co/edit/Yvlp6RNF69yiSq1HfMcf?p=preview
I have an Angular (1.2.1) app running UI-router (0.2.13), and the following state structure:
$stateProvider.state('home', {
template: "<div home></div>",
url: '/'
}).state('home.geo', {
url:'/geo/{geo}'
}
Transitioning from parent to child or between children with different {geo} parameter values works as expected. Transitioning from child to parent works - i.e. the contents of the template and $state.current change as expected - but the URL does not update in the browser.
To be clear, an example: I'm in /geo/california and I click a button with ui-sref='home'. I've confirmed that the correct href='#/' has been placed on the button, and clicking it causes the $state to transition back to the home state, but /geo/california remains in my address bar.
What am I missing here?
Update in respose to #UlukBiy's comment: No, home does not have a ui-view in its template. The ui-view is in the template of it's parent: The overall structure is:
<body>
<div app-nav></div>
<div ui-view></div>
</body>
So the home directive gets inserted into the ui-view, but it contains no ui-views of its own. Is that my problem? I'm new to UI-router, and assumed there was some low-level misunderstanding about the role of states vs. directives when I posted this. If so, please help me correct it.
This scenario should be working. There is a working example (click the blue button right-top to run example in separate window, showing the address bar)
I updated your state def a bit:
$stateProvider
.state('home', {
url: "/",
template: 'Home view <hr /> Geo view: <div ui-view></div>',
})
.state('home.geo', {
url:'^/geo/{geo}',
templateUrl: 'tpl.html',
})
All these links do work as expected:
<a href="#/home">
<a href="#/geo/california">
<a href="#/geo/czechia">
<a ui-sref="home">
<a ui-sref="home.geo({geo:'california'})">
<a ui-sref="home.geo({geo:'czech'})">
So, the most important change here is that for a child state we should use this url:
url:'^/geo/{geo}',
instead of the url:'/geo/{geo}'. Check the doc:
Absolute Routes (^)
If you want to have absolute url matching, then you need to prefix your url string with a special symbol '^'.
Check the working example here
I have a menu on my website, where the items have an active state. The default state is areas, then I can navigate through my website changing states.
<li ui-sref-active="active">
<a ui-sref="areas">
<span>Areas</span>
</a>
</li>
.state('areas', {
url: '/areas',
templateUrl : 'templates/areas.html',
controller : 'AreaCtrl'
})
In my areas.html template, I have a list, with items which can be clicked...:
<li ng-repeat="area in areas" ui-sref="areas.city({areaId: area.area_id, areaName: area.name})">
Now when one of these is clicked, I need to keep the active state on my menu. So the only way of doing this is via nested states...
.state('areas.city', {
url: "/:areaId/:areaName",
templateUrl: 'dist/templates/cities.html',
controller: 'CityCtrl'
})
However the problem is, my cities.html needs to be a totally new view (in place of where areas.html is), which isn't nested within areas (so I don't have a <ui-view> within areas.html).
I can, just not nest the view, so the state is .state('city', but then I lose the active state on the menu.
Any clue how I get around this?
You can activate the state in the main menu as like below
<li ng-class="{active: $state.includes('area') || $state.includes('areas.city')}">
<a ui-sref="areas">
<span>Areas</span>
</a>
</li>
Also, please apply the $state into $rootScope. So that you can access $state in any views.
myApp.run(function($rootScope, $state) {
$rootScope.$state = $state;
});
I am a newbie to ui-router , i would like to get a menu like below (its not a collapse thing, please see the plnkr )
menu1
a) submenu1
b) submenu2
c) submenu3
menu2
menu3
I managed to get the menus and submenus using the ui-router but not sure about the proper way to use the ui-router and used ui-sref-active="active" active the menu , the problem am facing is when I click on the submenu i would like to get the active to parent also.. ie if I click submenu1 , submenu2 or submneu3 i want to active its parent menu1.
here is the plunker : http://plnkr.co/edit/1kpmUiacrb3Aoo4E19O1?p=preview
There is an updated plunker, which does use the $state.includes method as defined here
Angular UI Router: How do I get parent view to be "active" when navigating to nested view?
the changes are: menu gets controller which puts $state into $scope:
"menu#dashboard": { templateUrl: "menu.html",
controller : function ($scope, $state){ $scope.$state = $state },
},
instead of this:
<li ui-sref-active="active"><a ui-sref=".menu1.submenu1">Menu 1</a></li>
<li ui-sref-active="active"><a ui-sref=".menu2">Menu 2</a></li>
<li ui-sref-active="active"><a ui-sref=".menu3">Menu 3</a></li>
we have to use defintion with ng-class:
<li ng-class="{active:$state.includes('dashboard.menu1')}"><a ui-sref=".menu1.submenu1">Menu 1</a></li>
<li ng-class="{active:$state.includes('dashboard.menu2')}"><a ui-sref=".menu2">Menu 2</a></li>
<li ng-class="{active:$state.includes('dashboard.menu3')}"><a ui-sref=".menu3">Menu 3</a></li>
BUT: this feature would be in a next ui-router release as we can see here:
feat(uiSrefActive): Also activate for child states.
cite
To limit activation to target state use new ui-sref-active-eq directive
Breaking Change: Since ui-sref-active now activates even when child states are active you may need to swap out your ui-sref-active with ui-sref-active-eq, thought typically we think devs want the auto inheritance.