We have an accordion on the page which sets hashes for the topics, to allow deep linking. The page runs on UI-Router in HTML5Mode. When clicking on the topics, Ui-Router reloads the resolves.
How can I stop this??
I tried:
reloadOnsearch = false in the state definition, which works great on search params but still reloads on hash change
if( $transition$.$to().name == $transition$.$from().name) {
$transition$.abort() // or return false; // or preventDefault()
}
Which works, but doesn't put the hash into the address, which is obviously needed.
How can I stop UI-Router from reloading the resolves and firing its state change events?
Update with more info:
I tried both,
<a ng-click="toggle();">
with $location.hash("value")
and
<a href="#value">
with preventDefault() in the controller, which (as expected) didn't made a difference.
Solution (hopefully)
This seems to work, in case someone faces the same problem:
$transitions.onBefore({}, function( transition ) {
if(transition.to().name == transition.from().name) {
const paramsCopy = Object.assign({}, transition.params());
const stateService = transition.router.stateService;
return stateService.target(transition.from(), paramsCopy);
}
})
What I understand from your question is you have a accordian with angular Js and the UI router reloads the page when you try to click on the accordian tabs.
Try replacing href attribute from data-target
<li><a data-target="#switchTabs" data-toggle="tab">Tabs</a></li>
Related
I am migrating an app from AngularJs to Angular 7. In the old ui-router I was able to update the location without reloading the state with below code.
this.syncLocation = function (paramObj) {
var params = _.clone($state.params);
params = _.merge(params, paramObj);
$state.transitionTo($state.current.name, params, {
location: true,
notify: false
});
};
However with new Angular & UI-Router I am unable to get this done. Not sure if it is due to Change Detection Strategy or changes to UI-Router itself.
syncLocation(paramObj) {
console.log("syncLocation", paramObj);
let params = _.clone(this.stateService.params);
params = _.merge(params, paramObj);
this.stateService.go(this.stateService.current.name, params, {
reload: false
});
}
I have created plunker to reproduce the problem. The problem is described in the component colors.component.ts link. In this plunker I don't want to reload the page even though I check/uncheck the checkbox.
The idea is that I have a complicated page where I cannot afford to lose the contents by reloading the page but still be able to update the location. It is a simplified page with the problem.
Any help is appreciated.
You can update the url with Location.replaceState()
See: replaceState()
Inject Location with di and use like this:
constructor(private location: Location) {
...
private syncLocation(){
this.location.replaceState(`whatever/state/or/path/you/need`);
}
}
There are other useful methods in Location such as Path you may want to reference.
I'am using Angular JS with UI-Router,
I want to reload state, when we click on the state link from the same state.
I fixed it with the following code,
<a ui-sref="page1" ui-sref-opts="{reload: true}">Page 1</a>
But it is tedious to add ui-sref-opts="{reload: true}" in all the links.
So I want a configuration or settings or code in angular js( or ui-router) to manage this globally. That is if we click on state link from the same state, the state should get reloaded.
Please help me to find a solution.
The way to go here is to adjust $state.go implementation, e.g. like this:
Changing the default behavior of $state.go() in ui.router to reload by default
In general we will use decorator to get control over $state behaviour
.config(function ($provide) {
$provide.decorator('$state', function ($delegate) {
// let's locally use 'state' name
var state = $delegate;
...
see that in action here
Why that should work is described here:
Difference between ui-sref and $state.go in AngularJS UI-Router
I have searched on StackOverflow for the last five hours and none of the related answers quite solve my problem. I have an UI-Router state that loads a long list of messages generated from a custom directive. This page is linked too in many places pointing to a different message. I want to scroll to the currently selected message.
I can get this to work using $anchorScroll if I surround the call with a $timeout. $timeout(function(){$anchorScroll()};) but if the $timeout is not there a call to $anchorScroll does nothing since the View has not completely loaded.
Here is most of the relevant code.
<message id='message{{message.id}}'
ng-repeat='message in messages'
message='message'
ng-class="{'current':current == 'message{{message.id}}'}" >
</message>
In the controller I set current to $scope.current = $location.hash(). This all works.
If I load the page like #/messages#message100 directly the page will correctly scroll. However, if from a different view I use the a link such as this:
<button ui-sref="message-state({'#':'message{{message.id}}'})>
Go To Message {{message.id}}
</button>
The page will not automatically scroll to the correct anchor since the message list has not been made yet. But by putting the call to $anchorScroll() in a $timeout I can make the page scroll.
I don't like using $timeout for this purpose. I know I am not supposed to manipulate the DOM in a controller like this.
I have tried registering the call to $anchorScroll() with many of the $stateProvider events such as:
$state.$on('$viewContentLoaded', function(event) {
$anchorScroll();
});
But even at the time the $viewContentLoaded fires the message list does not exist in the DOM and the page does not scroll.
IWhat is the best way to make the UI-Router scroll based on the $location.hash().
Even I was facing a similar situation and after days of try and error, I came up with this.
In ui router add an id parameter to the state on which you want to enable the scroll.
$stateProvider.state('index', {
url: '/',
params: {
id: null
}
})
Then in the html use ui-sref
<li><a ui-sref="index({id: 'about-us'})" >About Us</a></li>
At last in the app.run module detect the state change using
$rootScope.$on('$viewContentLoaded', function(event){
if ($state.current.name == 'index') {
if($stateParams.id) {
$anchorScroll.yOffset = 150;
$location.hash($stateParams.id);
$timeout(function(){$anchorScroll()}, 1000);
}
}
});
Hope this helps. Would do a plunkr if needed.
I have a nested state structure in my angular app using ui-router and I have this problem:
My state changes but the URL does not get updated to the child's state URL.
Previously, I had forgotten to include the <div ui-view></div> on the parent view and the URL got updated, but my child controller was not called.
Now that I have included the missing ui-view, the URL does not change, but everything else seems to work great (apart from the back/forward navigation on the browser of course...).
I have tried using { location: true } :
$state.go('parent.child', $stateParams, { location: true });
..but it didn't help.
Any ideas anybody?
I've been playing with UI-Router since ngRoute doesn't quite cover what I needed based on my different layouts requiring multiple nested views. What I can't figure out in UI-Router is how to load default nested views without having to click a link. I created a crude example of what I'm mean in a plunker
Essentially there are two main route within each there is a container which hosts nested views. I want to load a default view into them without have to click a ui-sref.
<h1>Auth Panel</h1> <-- main route 1
Just a container for login/forgot/reset
<hr/>
<a ui-sref="auth.login">Show Login</a><br> <-- can click to load nested view, but want to autoload
How to show automatically /login within the panel <br>
without having to click show login?
<div ui-view></div> <-- child to autoload with /login
Thanks
On your parent state add a param
.state('parentState', {
//...
params: {
autoActivateChild: 'parentState.childState'
}
//...
})
And add this somewhere
$rootScope.$on('$stateChangeSuccess', function(event, toState){
var aac;
if(aac = toState && toState.params && toState.params.autoActivateChild){
$state.go(aac);
}
});
If you wanted to navigate automatically to a default child state when the parent loads, you could trigger a click on that particular ui-sref in your controller.
angular.element("#childElementId").trigger('click');