290

What is the method for redirecting the user to a completely external URL in Angular 2. For example, if I need to redirect the user to an OAuth2 server in order to authenticate, how would I do that?

Location.go(), Router.navigate(), and Router.navigateByUrl() are fine for sending the user to another section (route) within the Angular 2 app, but I can't see how they could be used to redirect to an external site?

Michael Oryl
  • 20,856
  • 14
  • 77
  • 117
  • 10
    Note: If your external URL doesn't contain http:// or https://, Angular 4 will treat the URL as an internal route. In case anyone else is struggling with that. – aherocalledFrog Apr 05 '18 at 20:27
  • Wow this thread is hilarious. Imagine explaining the benefits of Angular and then explaining navigating to an external URL. Estimated effort = 1 hour – AlxVallejo Feb 08 '23 at 15:39

15 Answers15

342

You can use this-> window.location.href = '...';

This would change the page to whatever you want..

Zoe
  • 27,060
  • 21
  • 118
  • 148
Dennis Smolek
  • 8,480
  • 7
  • 30
  • 39
  • 3
    Ugh, I tried calling it as a function for some reason rather than just changing the value. Setting the value directly works. – Michael Oryl Dec 17 '15 at 18:15
  • 12
    Just remember that directly referencing the window will limit your code to platforms with a window object. – ender Oct 26 '16 at 15:08
  • 2
    @ender isn't there an alternative to it? There might be scenarios where we genuinely want to redirect to external links. Sure, we can use window.location.href, but like you say, it has its disadvantages. If there is a supported API in Angular, that would help better. – Krishnan May 07 '17 at 21:05
  • 1
    Sure, but that is 99% of all platforms that run javascript and need to do a page redirect. Even phantom/casperJs respect the window object. You can call `document.location.href` or even `Location.href` as they all refer to the same object. [Location Reference](https://developer.mozilla.org/en-US/docs/Web/API/Location) – Dennis Smolek May 08 '17 at 01:33
  • 2
    @DennisSmolek But if you try to compile this into an android app using Universal, wouldn't this behavior fail? – ender May 12 '17 at 13:50
  • @ender what do you mean "Universal?" NativeScript doesn't have *window* that's true, but it also wouldn't be used to 'redirect' anything like the OP asked. You'd call a webview or an external app if you wanted a site and you'd use the router for internal pages. Windows Universal Platform (UWP) respects window, so does Ionic & Cordova. – Dennis Smolek May 12 '17 at 20:28
  • @DennisSmolek, I believe ender means [angular universal](https://github.com/angular/universal), server side rendering. Is there a "safe" way to navigate to external URL in angular? – Wilhelmina Lohan Sep 11 '17 at 21:38
  • Not trying to be rude, I'm trying to understand, so to be clear @WilliamLohan, you're saying in the Angular Universal app for server side rendering that you want the angular compiler to render all the native pages and views, then also render a different website altogether? I don't think that's ever a situation the server-side would handle either. Serverside rendering still produces HTML, and your user would still use a browser to consume it so a basic link or `location.href`would still likely be the way to go... – Dennis Smolek Sep 25 '17 at 21:57
  • @DennisSmolek you are right that would be a bad design, but I've always been under the impression that in general it is bad practice to use the window object in angular because if it is possible for that code to run while server side rendering you'd get an undefined. So you'd think they'd have a solution. – Wilhelmina Lohan Oct 02 '17 at 15:13
  • any way using `routerLink` ? – Pardeep Jain Mar 26 '18 at 07:04
  • `Binding to event property 'onclick' is disallowed for security reasons, please use (click)=...` – Toolkit Jul 02 '18 at 16:16
  • @DennisSmolek can you help me to solve this question? If i developed login in Angular6 and after login if user have admin permissions he should redirect to Laravel (5.5) backend. then angular frontend and laravel backend should know who is logged now.can u help me to solve this. – RuwanthaSameera Mar 19 '19 at 09:54
  • 1
    @DennisSmolek wouldn't it make testing of method with `window` reference more difficult? – Eugene Jul 16 '19 at 12:26
  • @Eugene correct, without the usage of any dependency, it's really hard to do. A better solution is proposed by Brian (https://stackoverflow.com/a/42452665/2158015) such that you can provide a mock object instead of the actual document. – Didii Jan 29 '20 at 13:05
  • I tried to use this as a relative URL using a proxy but didn't work for me. Later, I had to use the original IP. – Ashraful Sep 08 '21 at 12:11
216

An Angular approach to the methods previously described is to import DOCUMENT from @angular/common (or @angular/platform-browser in Angular < 4) and use

document.location.href = 'https://stackoverflow.com';

inside a function.

some-page.component.ts

import { DOCUMENT } from '@angular/common';
...
constructor(@Inject(DOCUMENT) private document: Document) { }

goToUrl(): void {
    this.document.location.href = 'https://stackoverflow.com';
}

some-page.component.html

<button type="button" (click)="goToUrl()">Click me!</button>

Check out the platformBrowser repo for more info.

Ollie
  • 1,641
  • 1
  • 13
  • 31
Brian
  • 2,494
  • 1
  • 16
  • 21
  • Would the target site know that the request is coming from our app, since the requirement here is to redirect for login purpose and hence the SSO app should redirect back to our app after success – NitinSingh Jun 11 '17 at 20:51
  • 6
    In angular 4, DOCUMENT should be imported from `@angular/common` (i.e. `import { DOCUMENT } from '@angular/common';`), but otherwise this works great! See https://github.com/angular/angular/blob/master/packages/platform-browser/src/dom/dom_tokens.ts – John Oct 23 '17 at 21:21
  • 4
    what is the purpose of injecting document this way `@Inject(DOCUMENT) private document: any` – Sunil Garg Nov 22 '17 at 12:48
  • 3
    @SunilGarg Injecting `DOCUMENT` makes it easier to replace the document object with a mock in unit tests. It also allows for an alternative implementation to be used on other platforms (server/mobile). – eppsilon Mar 14 '18 at 21:35
  • This works great with SSR(ng universal) as well. Thanks! – Poulad Oct 07 '18 at 17:36
  • how do I redirect with params? e.g. pass `{ company : "test" }` to another url which is angular app – Nitin Sawant Mar 06 '19 at 11:44
  • 5
    For strict typing I use, `constructor(@Inject(DOCUMENT) private document: Document) { }` – Ian Jamieson May 29 '19 at 01:37
  • I am getting the error: ERROR NullInjectorError: R3InjectorError(AppModule)[Document -> Document -> Document]: NullInjectorError: No provider for Document! – Sami Mar 30 '22 at 09:47
45

The solution, as Dennis Smolek said, is dead simple. Set window.location.href to the URL you want to switch to and it just works.

For example, if you had this method in your component's class file (controller):

goCNN() {
    window.location.href='http://www.cnn.com/';
}

Then you could call it quite simply with the appropriate (click) call on a button (or whatever) in your template:

<button (click)="goCNN()">Go to CNN</button>
Community
  • 1
  • 1
Michael Oryl
  • 20,856
  • 14
  • 77
  • 117
33

I think you need à target="_blank", so then you can use window.open :

gotoGoogle() : void {
     window.open("https://www.google.com", "_blank");
}
JustLearning
  • 3,164
  • 3
  • 35
  • 52
abahet
  • 10,355
  • 4
  • 32
  • 23
17

If you've been using the OnDestry lifecycle hook, you might be interested in using something like this before calling window.location.href=...

    this.router.ngOnDestroy();
    window.location.href = 'http://www.cnn.com/';

that will trigger the OnDestry callback in your component that you might like.

Ohh, and also:

import { Router } from '@angular/router';

is where you find the router.

---EDIT--- Sadly, I might have been wrong in the example above. At least it's not working as exepected in my production code right now - so, until I have time to investigate further, I solve it like this (since my app really need the hook when possible)

this.router.navigate(["/"]).then(result=>{window.location.href = 'http://www.cnn.com/';});

Basically routing to any (dummy) route to force the hook, and then navigate as requested.

Henry Arousell
  • 189
  • 1
  • 5
  • Thanks a lot for this solution. I was searching for some time for a solution and managed only to open an external link on a new tab, but on same tab all the window.open, location.pathname/href.... didn't let me to navigate away from my site. This is the most clean and correct way to handle routing out of the angular app! – EranKT Feb 03 '22 at 08:24
13

in newer versions of Angular with window as an any

(window as any).open(someUrl, "_blank");
WizardsOfWor
  • 2,974
  • 29
  • 23
8

There are 2 options:

  1. if you want to redirect in same window/tab

     gotoExternalDomain(){
         window.location.href='http://google.com/'
     }
    
  2. if you want to redirect in new tab

     gotoExternalDomain(){
         (window as any).open("http://google.com/", "_blank");
     }
    
sravan ganji
  • 4,774
  • 3
  • 25
  • 37
  • 2
    Hi! Can you explain what's `"_blank"` for since link is opened in new tab without it as well? – tz0 Jul 01 '21 at 15:16
  • @tz0 It opens an URL in a new tab. – Co ti Apr 12 '22 at 15:46
  • @Coti but it opened that url without "_blank" as well – tz0 Apr 18 '22 at 15:30
  • In other browsers the "_blank" can be required. But for example the latest chrome does not require this specification but other browsers would define it as "_self" -> you would redirect to the same tab. – Rejja Kubzek Aug 21 '23 at 09:38
5

I did it using Angular 2 Location since I didn't want to manipulate the global window object myself.

https://angular.io/docs/ts/latest/api/common/index/Location-class.html#!#prepareExternalUrl-anchor

It can be done like this:

import {Component} from '@angular/core';
import {Location} from '@angular/common';
@Component({selector: 'app-component'})
class AppCmp {
  constructor(location: Location) {
    location.go('/foo');
  }
}
user3220080
  • 75
  • 1
  • 2
  • 1
    For me, this just changes the URL and the app state doesn't change (actual route looks the same). Even 'location.replaceState('/') did not act as I expected. `router.navigate(['/']);` is what did it for me. – Matt Rowles Nov 03 '16 at 22:54
  • 2
    Angular 2 Location doesn't sound applicable. The docs state that the purpose of location is: "Location is responsible for normalizing the URL against the application's base href." Using this to redirect to a URL within the application may be appropriate; using it to redirect to an external URL doesn't seem to fit with docs. – J. Fritz Barnes Feb 04 '17 at 00:14
5

I used window.location.href='http://external-url';

For me the the redirects worked in Chrome, but didn't work in Firefox. The following code resolved my problem:

window.location.assign('http://external-url');
naveen
  • 53,448
  • 46
  • 161
  • 251
Laura Chesches
  • 2,493
  • 1
  • 19
  • 15
5

After ripping my head off, the solution is just to add http:// to href.

<a href="http://www.URL.com">Go somewhere</a>
Joel
  • 327
  • 4
  • 3
5

You can redirect with multiple ways:

like

window.location.href = 'redirect_url';

another way Angular document:

import document from angular and the document must be inject as well as bellow otherwise you will get error

import { DOCUMENT  } from '@angular/common';
export class AppComponent {
     constructor(
       @Inject(DOCUMENT) private document: Document
    ) {}
   this.document.location.href = 'redirect_url';
}
Siraj Ali
  • 526
  • 6
  • 13
2

None of the above solutions worked for me, I just added

window.location.href = "www.google.com"
event.preventDefault();

This worked for me.

Or try using

window.location.replace("www.google.com");
Rishi0405
  • 354
  • 1
  • 11
  • Did you try doing window.open(url, "_self") ? I think that you had a problem with overwriting your current URL because of used modules. – Rejja Kubzek Aug 21 '23 at 10:08
0

To use @Inject, you must import it. I didn't see this in any of the answers.

TS file:

import { Component, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';

@Component({
  selector: 'app-my-comp.page',
  templateUrl: './my-comp.page.component.html',
  styleUrls: ['./my-comp.page.component.scss']
})
export class MyCompPageComponent {

  constructor(
    @Inject(DOCUMENT) private document: Document
  ) { }

  goToUrl(): void {
    this.document.location.href = 'https://google.com/';
  }

}

HTML file:

<button type="button" (click)="goToUrl()">Google</button>
Cesar Devesa
  • 990
  • 6
  • 14
0

Most of the current replies are optimal, but for cleaner code I would recomend the use of window instead of an injected reference of document as it is nothing less than a duplicate reference of the window itself. Only case where it better to use is when you cannot directly use the window.

const url : string = "https://stackoverflow.com/questions/34338440/how-to-redirect-to-an-external-url-in-angular2" 
window.open(url, "_blank")
//window.open(url, "_self")
//window.open(url, "_parent")
//window.open(url, "_top")

This code will open a window whose second parameter which is the target atribute that will decide where the URL will be opened.

The specific target atribute values are these: (mozilla)

_self: the current browsing context. (Default)

_blank: usually a new tab, but users can configure browsers to open a new window instead.

_parent: the parent browsing context of the current one. If no parent, behaves as _self.

_top: the topmost browsing context (the "highest" context that's an ancestor of the current one). If no ancestors, behaves as _self.

With this you can have a bit cleaner solution on where the new URL should be opened for the best experience of the end user

In any case you can replace router.navigate with

window.open("relativePathFromCurentURL","_self") 

to navigate through your website. I can only recomend you this usage for cases where you do not want to import routing to some components.

Rejja Kubzek
  • 81
  • 1
  • 6
-1

In your component.ts

import { Component } from '@angular/core';

@Component({
  ...
})
export class AppComponent {
  ...
  goToSpecificUrl(url): void {
    window.location.href=url;
  }

  gotoGoogle() : void {
    window.location.href='https://www.google.com';
  }
}

In your component.html

<button type="button" (click)="goToSpecificUrl('http://stackoverflow.com/')">Open URL</button>
<button type="button" (click)="gotoGoogle()">Open Google</button>

<li *ngFor="item of itemList" (click)="goToSpecificUrl(item.link)"> // (click) don't enable pointer when we hover so we should enable it by using css like: **cursor: pointer;**
Linh
  • 57,942
  • 23
  • 262
  • 279