AngularUI pattern to forward to url after login - angularjs

So I have a scenario where a user can provide a url like:
http://localhost:8080/#/component?id=1234
The first thing AngularUI does is check if the user is authorized.
If it's not authorized it's forwarded to the login page using
$state.go("login");
My intention is to record the url in
$rootScope.$on("$stateChangeStart"....
Save it in the rootscope and then forward to that url once the login is done.
However, I can't seem to find a way to maintain the url with the query parameter component?id=1234. should I use $location or $state. I can get it to work with the state name only (using $state) but not with parameters.

I don't know if your solution is the best one there. But if you want to do that, you can simply write a function like this:
$rootScope.$on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams){
/* your code here */
})
and you can navigate to any state with any parameters by doing something like:
$state.go("state_name",{/*parameters as an object e.g. id:1234*/});
You can also read the wiki on angular ui-router's page.
Hope I could answer your question.

Actually turns out I can just use the $location object.
storing $location.url() in the rootScope. and then navigating using $location.url(savedUrl) to redirect it back.

Related

$location.path change hash to %23 & .hash is not working fine

I want to redirect to the another page & focus should be on the some DIV with id let's say 'some-div-id'.
I tried following
$location.path('/' + $scope.config_path.school + '/' +
$routeParams.someUrl + '/#some-div-id')
This is working fine but it first change # to %23
Like
/%23some-div-id #If '#' is not already present in the URL
/%23some-div-id#some-div-id #If '#' is laready present in the URL
/#some-div-id
I also tried following
$location.path('/' + $scope.config_path.school + '/' +
$routeParams.someUrl + '/').hash('some-div-id')
it is creating a proper URL but not scroll down to the DIV with id some-div-id
EDITED
app.run(function($rootScope, $location, $anchorScroll, $routeParams) {
$rootScope.$on('$routeChangeSuccess', function(newRoute, oldRoute) {
setTimeout(function() {
if ($location.hash()) {
$anchorScroll($location.hash());
}
});
});
})
app.controller('MainCntrl', function($scope, $location, $anchorScroll, $routeParams) {
});
Also i tried $location.path & $location.url
Try using $location.url instead of $location.path .
As per the documentation , $location.path only changes the path whereas $location.url changes the path, search and hash.
So the code would be like
$scope.goto = function() {
$location.url('pageone#one');
};
Where pageone is URL of the state and #one is the ID
Also to make it work when directly visiting the URL with the ID in it , use $anchorScroll . On the $stateChangeSuccess event , checking weather $location.hash is present or not.If present , then call $anchorScroll . The code would look like
.run(function($rootScope, $location, $anchorScroll,$timeout) {
$rootScope.$on('$stateChangeSuccess',
function(event, toState, toParams, fromState, fromParams) {
$timeout(function() {
if ($location.hash()) {
$anchorScroll();
}
});
});
})
Example - http://plnkr.co/edit/4kJjiMJImNzwLjRriiVR?p=preview ( For seeing change in URL check http://run.plnkr.co/plunks/4kJjiMJImNzwLjRriiVR/#/pageone )
This behavior is expected. Angular will not allow a second # in your url by default, thus every # beyond the first one will be escaped, resulting in %23 which is the escape character for #: http://www.w3schools.com/tags/ref_urlencode.asp.
You could try enabling html5mode by adding the following to your .config block:
$locationProvider.html5Mode({
enabled: true
});
If that doesn't solve your problem, or if you need to support support IE8, your best bet would probably be to use $anchorScroll().
Here's the documentation.
In your app, you could pass the id of the div you want to scroll to as a parameter in your url (using $routeParams or ui-router's $stateParams), and then call a function that will scroll to that div immediately on page load, such as:
$scope.scrollTo = function(id) {
$location.hash(id);
$anchorScroll();
}
Please also read the following for a more detailed explanation on how to use $anchorScroll() for your specific problem:
How to handle anchor hash linking in AngularJS
Namely, this particular section:
Set up your angular routing as usual, then just add the following code.
app.run(function($rootScope, $location, $anchorScroll, $routeParams) {
//when the route is changed scroll to the proper element.
$rootScope.$on('$routeChangeSuccess', function(newRoute, oldRoute) {
$location.hash($routeParams.scrollTo);
$anchorScroll();
});
});
and your link would look like this:
Test/Foo
$location.path(page);
just add the dependency in ur controller by add $location,
This method redirects you on this route, without any error.
In ng-book, there is something about %13 signs replacing normal letter.
Unfortunately, it's about different topic - it is about an $http or xhr api call through REST, where there are two modes ( same would be here ) - one normal mode and second JQuery like. It turned out that jquery adds these %13 signs to things like arr[]=1.
Why i am saying this?
Because after solution comes libraries and functions which support marginal conditions.
The situation in Your question is quite simple. There is $location service, which is solution and urls are created simillary in two modes, which are hashbang and not hashbang.
In problem with jquery parameters, developers provided library for exchanging jquery parameters to normal. There are many converters in real life, like pdf to doc etc.
Please look at short chapter in this book.
It is stated that in html5 mode, you cannot have two hashes in url, but in hashbang mode you can.
Browser cannot know which hash is to go to in hashbang mode. The support for this is anchorScroll service.
I haven't checked if this works in this case but try to configure your app with AnchorScrollProvider:
.config(function($anchorScrollProvider){
$anchorScrollProvider.disableAutoScrolling();
});
Then as i written, you can inject $anchorService service to any place in your app ( especially in controller binded to view containing some-div-id div ) And call anchorScroll() function of this service at any chosen time.
I cannot test it right now so this is theoretical answer.
I had the same problem before and this post helped me out.
Let's hope it is going to help you aswell, if it doesn't let me know so I can help you find another solution.
Good luck.

ui-router: open modal on $stateChangeEvent

Some states in my app require further authentication. Eg a Edit state should prompt the user to enter a one time password.
I would be nice to solve this horizontally: attach metadata to the states requiring extra auth (ie state.requiresExtraAuth: true), and plug some modal logic on the state change events. NOTE: What I am after is that the state does indeed load and the user can see it, but a modal forbids the user from continuing without entering the password.
I tried adding a 'onEnter' property to the toState object param I get in the event listener function, but it didn't work :).
Is something like that possible/how would you go about designing this use case?
In run method of you application.
add.run(function($rootScope, $state, $modal){
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
if(toState.name != 'app.home') {
$state.go('app.login');
// or open modal
$modal.open({...});
}
});
});
This event will help you to check what state user try to access and redirect to login form if needed.

How to get requested route in angular when otherwise was used

I trying to determine what the original route was when angular defaulted to the .otherwise route.
I can't see any information in the documentation on this.
Now I am considering creating a service that intercepts the broadcast for route change start and storing that value. But this seems overkill for something so simple.
So is there a better way to determine this information?
You can use the $routeChangeSuccess event and get the previous route in one of the callback parameters of this event.
PLUNKER
e.g.
app.run(function($rootScope) {
$rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
if(previous && previous.$$route) {
console.log(previous.$$route); // displays previous route
}
});
});
As a reference regarding its documentation, you can see this question I've answered.

With angularjs and ui-router, how to disable the navigator history for one view change

I want the current state change not to be saved in navigation history. Then when user clicks 'back', the view will be skipped and go back to previous page.
Can I temporally disable the state change to be saved in navigator history?
I believe this where ui-router's option parameter with value { location:'replace'} is intended for.
The documentation explains:
location Boolean or "replace" (default true), If true will update the
url in the location bar, if false will not. If string "replace", will
update url and also replace last history record.
It seems that there's an issue (see it here on GitHub) to be fixed though.
In the spirit of stackoverflow I will try to answer the question and not mention that what you are asking for is a truly horrible hack ;-)
I think you may need something like this. (the code is coffeescript)
angular
.module 'app', ['ui.router']
.run ($rootScope, $state) ->
$rootScope.$on '$locationChangeStart', (event) =>
if $state.is 'bad-state'
event.preventDefault()
$state.go 'good-state'
When the location changes (you could also use $stateChangeStart) you check the current state and if it is the state you don't want then you go to the state you do want. the event.preventDefault() effectively halts the processing of the originally requested state.
If you need an even dirtier version then you could check the location urls instead of the states and use $location.url to perform the transfer, like this:
angular
.module 'app', ['ui.router']
.run ($rootScope, $location) ->
$rootScope.$on '$locationChangeStart', (event, nextLocation) =>
if nextLocation is '/bad/location'
event.preventDefault()
$location.path '/good/location'
This worked for me.
$rootScope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams){
event.preventDefault();
window.history.forward();
});

Receive an event on direct page visit from address bar, Angular JS - ui-router

guys I am working on an angular js app which uses ui-router for deep linking and routing. I want to set up a variable on the $rootScope every time a state is visited/changed. I am able to accomplish that on subsequent state transitions via listening to $stateChangeSuccess but since the app is deep linked, I want to set the same variable when a state is directly hit from the address bar.
When I hit a specific URL from address bar e.g. Home/Summary/Change, $stateChangeSuccess doesn't fire hence I am not able to set the value.
Any suggestions on how I can listen to EACH state visit on my $rootScope.
You may use combination of $locationChangeStart and $route.current:
$rootScope.$on('$locationChangeStart', function (event, next, current) {
if(!$route.current) {
$rootScope.myVar = ...
}
});
I found a work around for this. I was not able to get $stateChangeSuccess on the first visit to a page so on initialization i called the function explicitly.
example code
var handle = function(){
//do something ...
}
$scope.$on('$stateChangeSuccess', handle); // call handle on each state change
handle(); // will only be called on initialization
might not be the cleanest way but it works
In the meantime they have implemented a $urlRouterProvider where you can add a when:
app.config(function($urlRouterProvider){
// when there is an empty route, redirect to /index
$urlRouterProvider.when('', '/index');
// You can also use regex for the match parameter
$urlRouterProvider.when(/aspx/i, '/index');
})
So if you like to have Home/Summary/Change matching a state, you would write something like $urlRouterProvider.when('Home/Summary/Change','myhomestate') then the $stateChangeSuccess should fire correct.
For more details about that provider look at https://github.com/angular-ui/ui-router/wiki/URL-Routing#urlrouterprovider

Resources