AngularJS $routeProvider otherwise catches my external redirections - angularjs

I'm using $routeProvider in AngularJS with many routes configured. The "otherwise" section
is configured, so it redirects all the unknown routes to the main page of my application.
All I want is to redirect the browser from my controller to an external URL, but I cant.
I tried to use $window.location = external, window.location.href = external, but they doesnt work. The routing API redirects me to the default page set in otherwise every single time.
How could I achieve this with / or without major hacks. Unfortunately, It have to be done via JavaScript code from my controller.
Thanks in advance

That might not fully answer your question but to navigate outside of route scope you can use this
Links that contain target element
Example: link
Absolute links that go to a different domain
Example: link //this one might actually be of use for you
Links starting with '/' that lead to a different base path when base is defined
Example: link

AngularJS's routing is for routing within the page.
You should use native location.href for this.
Edit: can you give me a plunker for this? did you try something along this line yet?
$scope.path="http://www.google.com";
$scope.redirect = function(path){
location.href = path;
};
with
<button ng-click="redirect(path)">Go there</button>

Related

AngularJS ui.router -- How to keep URL patterns manageable

If we are using "ui.router" of angular JS module, will that module take control of all the URL navigation in the entire page?
I am using the $stateProvider.state method to register the mappings of URLs and States but as I am using it, I am observing that the state provider is taking control of routing all URL patters. For example, if I am having a jquery tabs pane in the same page somewhere, it is not working. The reason being, the jquery tabs are based on the HREF of the Anchors and this ui-router is taking charge of mapping them as well, to some states.
Can someone please confirm if it really is supposed to work like this?
No, as per I know, it should work fine with HREF,for example
link
In your case, for tabs you are specifying #(hash) in href and thats why its going through ui-router, I would suggest you to use <uib-tab> instead of simple jQuery tabs and thing will work as you needed.
If you are using # in anchor tag then it will always try to match it with url and if not found then it will redirect to defualt one but you can actually intercept url change request in run function and use preventDefault function for specific request which will stop url change request

Passport.js, Express.js, and Angular.js routing: how can they coexist?

I apologize this question turned out a bit long, but I have worked on this for some time and really needed to explain all the story.
Background: App based on MEAN stack, trying to authorize Facebook logins using Passport.js.
Following Passport.js guide I implemented something similar to:
// HTML
Add a Facebook login
// send to facebook to do the authentication
app.get('/connect/facebook',isLoggedIn, passport.authorize('facebook',
{ scope : 'email' })
);
// handle the callback after facebook has authorized the user
app.get('/connect/facebook/callback',
passport.authorize('facebook', {
successRedirect : '/profile',
failureRedirect : '/profile'
}));
Notice the target=_self in the html in order to skip Angular routing.
Clearly, authorization works fine. However, redirection does not work, as the routing is handled by Angular. After authorization I never land on /profile (but on the default Angular route).
Therefore, I tried with a custom callback as suggested by Passport.js here, with the hope of passing json data to Angular, and let Angular do the routing. I ended up doing something like:
// In the controller
$http.get("/connect/facebook").success(function(data){
// here I wait for json data from the server and do the routing
});
// I call this route from Angular
app.get('/connect/facebook',isLoggedIn,passport.authorize('facebook',
{ scope : 'email' })
);
// But Facebook lands here!
app.get('/connect/facebook/callback',function(req, res, next) {
passport.authorize('facebook', function(err, user, info) {
res.json({something:smtg});
...
Clearly custom callbacks work for local-login, as Passport.js explains. But here do you see the problem? I call /connect/facebook from Angular, but I should receive some json from /connect/facebook/callback.
I am about to give up Passport, but before this, do you see any solution which would allow landing on /profile after FB authorization, perhaps with a custom message? Many thanks for reading through.
EDIT:
The same question had been reported as an issue on the Passport-Facebook GitHub account. Some additional attempts have been posted there, but not quite the fix yet.
This is a bit more in depth than can be described in one answer, but I'll try to start pointing you in the right direction.
Essentially, Angular.js routes are not really HTML routes at all, but an internal route structure that happens to use the URL for use of the end user. Remember that Angular.js is a client script, and that a full page reload is not desired, as this will reload the entire script. Therefore, /# is used to trick the browser into jumping to a specific bit of code within the already loaded script. (as opposed to the traditional anchor location in the HTML document). Unfortunately (or fortunately), HTML 5 mode allows you to hide the /# part of the url, so instead of seeing http://somesite.com/#/someroute you just see http://somesite.com/someroute. Rest assured, however, that the /# is still there. Angular.js uses the HTML5 pushState (AKA HistoryAPI) to perform the magic replacement.
Given this, if you have called a server route, you are outside the Angular.js script, and any call to load the angular script again will start from the very beginning. You can't actually call your Angular.js route from the server without a full reload. Therefore, you are really doing a double route redirect here. Your server should be calling it's default route for angular, appending /#/someroute to the call. The angular.js page will load, parse off the /#, and redirect to the correct angular route. Keep in mind, however, that if there was any dependency on already loaded objects, those are no longer in memory. Therefore, any route accessed this way should operate as if it is an entry point to your application.
Effectively, you should try using successRedirect : '#/profile', keeping in mind that the profile route in angular should be treated as an app entry point.
Hopefully this gets you started.
If #Claies's way is not working, is it possible you have not get rid of the #= fragment from the facebook callback.
Have a read of this post

AngularJs - Determining the next location's route in $locationChangeStart

Recently I found out about the undocumented $locationChangeStart event in AngularJS when trying to determine where in the framework I should be redirecting users to the login page if their session is invalid.
I'm listening for the event using the following:
$scope.$on("$locationChangeStart", function (event, nextLocation, currentLocation) {
// Logic goes here
});
where nextLocation and previousLocation are absolute urls to locations within the app.
My question is this: Does AngularJS expose the ability to be able to match a url against a route, much like its internal routing engine does to see if an absolute URL matches a defined route?
If not, what would be the best way to detect a route based on an absolute URL?
I located the relevant source code lines in the AngularJS github project. Here is the function that it uses to match the URL to a route:
Since this functionality is not exposed by Angular I decided to come up with a rudimentary way of matching the URL to a route since the routes I was matching were relatively simple compared to implementing the same route matching that Angular does.
It ain't pretty, but it works..

Angularjs Normal Links with html5Mode

I am working with angularjs in html 5 mode. Which appears to take control of all href's on the page. But what if I want to have a link to something within the same domain of the app but not actually in the app. An example would be a pdf.
If i do <a href="/pdfurl"> angular will just try to use the html5mode and use the route provider to determine which view should be loaded. But I actually want the browser to go to that page the normal way.
Is the only way to do this is to make a rule with the route provider and have that redirect to the correct page with window.location?
in HTML5 mode, there are three situations in which the A tag is not rewritten:
from the angular docs
Links that contain a target attribute. Example: link
Absolute links that point to a different domain Example: link
Links starting with '/' that lead to a different base path when base is defined Example: link
so your case would be 1. add target="_self"
As of Angular v1.3.0 there is a new rewriteLinks configuration option for the location provider. This switches "hijacking" all the links on the page off:
module.config(function ($locationProvider) {
$locationProvider.html5Mode({
enabled: true,
rewriteLinks: false
});
});
While disablig this behavior for all links may not be your intention, I'm posting this for others who, like me, want to use $location in html5 mode only to change the URL without affecting all links.
If you don't want Angular to take control of the href. Place a target attribute on the link.
So PDF will by pass the html5mode and the routeProvider and the browser will just go to that url.
Other solution. All links will work normally (reload page). Links marked by ng-href="/path" will play on pushState. Small JS hack help with it.
.config(["$locationProvider", function($locationProvider) {
// hack for html5Mode customization
$('a').each(function(){
$a = $(this);
if ($a.is('[target]') || $a.is('[ng-href]')){
} else {
$a.attr('target', '_self');
}
});
$locationProvider.html5Mode(true);
}])

AngularJS application links/routes in anchor tag with HTML5 mode

How do I link to other AngularJS application locations within an anchor A tag? I am using HTML5 hashless mode and would like to avoid having the page actually reload.
For example, in non-HTML5 mode I would do this:
<a href='#/path'>Link</a>
In HTML5 mode I can do this:
<a href='/path'>Link</a>
But this actually causes the browser to reload the new URL. I've also tried using ng-href and also the /#/path syntax but none of them seem to work as I'd like.
How do I properly link from an anchor tag?
Update:
It seems like this is possible without using $location, you just have to keep the same base link. From the docs:
When you use HTML5 history API mode, you will need different links in different browsers, but all you have to do is specify regular URL links, such as: link
When a user clicks on this link,
In a legacy browser, the URL changes to /index.html#!/some?foo=bar
In a modern browser, the URL changes to /some?foo=bar
In cases like the following, links are not rewritten; instead, the browser will perform a full page reload to the original link.
Links that contain target element. Example: link
Absolute links that go to a different domain. Example:
Links starting with '/' that lead to a different base path when base is defined. Example: link
Old:
You should use the $location service. Inject it into the controller and put it on the $scope (or in a convenience method):
function MainCtrl($scope,$location){
$scope.goto = function(path){
$location.path(path);
}
}
<a ng-click="goto('/path')">Link</a>
This worked for me in html5mode enabled.
<a ng-href='./path'>Link</a>
Angular Js uses hash prefix followed by exclaimation. Hence if you want to use the anchor tag then have it this way.
Link
https://docs.angularjs.org/tutorial/step_09

Resources