How to get base url in angular 5?

My current url is http://localhost:4200/test/dashboard.

I want to print base url i.e http://localhost:4200 using angular 5 features.


Solution 1:

The other answers here cover quite a range of options:

  • location
  • window.location
  • document.location
  • DOCUMENT / Document
  • Location
  • LocationStrategy
  • PlatformLocation

TLDR; for simple situations the globally available DOM location may be enough for your needs. However, you probably really want an Angular Location instance. And, in certain circumstances, LocationStrategy may also be useful.

You can access the DOM location directly without needing to import anything:

foo(): void {
  console.log(location.origin);
  console.log(location.href);
  console.log(location.pathname);
}

If you want to use the Angular Location and LocationStrategy then you have to pull them in like so:

import { Location, LocationStrategy } from '@angular/common';

constructor(private location: Location, private locationStrategy: LocationStrategy) { }

foo(): void {
  console.log(this.location.path());
  console.log(this.location.prepareExternalUrl('/'));
  console.log(this.locationStrategy.getBaseHref());
}

You can use prepareExternalUrl to e.g. construct URLs that refer to assets:

const url = this.location.prepareExternalUrl('assets/svg/icons.svg');

If you're serving everything out from directly under /, there may not seem to be much point using the Angular Location but if you've set your application's base href to be something other than / or if you're doing more complicated things with paths then Angular Location will help you work with this kind of thing correctly.

If prepareExternalUrl doesn't seem to be picking up your base href, see the notes about this at the end of this answer.

In some examples, you'll see it stated that you have to configure APP_BASE_HREF in order for things to pick up your base href. This is not the case anymore, see the end of this answer for more on this.

Note: by default Angular uses the location strategy PathLocationStrategy but if you've changed things to use HashLocationStrategy then prepareExternalUrl and other functions will not work the same way. However, if you're using HashLocationStrategy you probably know what you're doing, so I won't go into this here.

The full details

Let's have a look in turn at each of the entities listed above.

1. location, window.location and document.location are of type Location, come directly from the DOM and are available as global variables, i.e. you don't have to import or inject them in any way.

These are all ways of getting at the same thing. location and window.location are literally the same thing (window can be referred to explicitly but it is also the implicit global this). location and document.location are essentially the same thing, see this SO answer for more details on this.

You can find the MDN documentation for Location here.

So if the DOM Location is all that you want, I would just use location. Some people like to be explicit that they're accessing the window object and prefer to use window.location. The location field of document has a confusing history and seems to be the least popular way to access a DOM Location instance.

2. Elsewhere, you can see people using the Angular dependency injection token DOCUMENT like so:

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

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

Then you can access this.document.location. Again, this is simply a DOM Location instance, so if this is what you want, why bother injecting it when you can access it directly as location? The this.document and the globally available document mentioned above are both of type Document and, in a browser context, they are the same thing. So the only reason you'd inject it is if you're working in a non-browser context.

You can find the Angular documentation for DOCUMENT here and the MDN documentation for Document here.

3. Finally three Angular entities - Location, LocationStrategy and PlatformLocation.

Confusingly, Angular has used the same name for their location type (i.e. Location) as the type of location etc. up above. The DOM Location is available globally and doesn't need to be imported, the Angular Location needs to be imported from @angular/common.

The Angular entities Location, LocationStrategy and LocationStrategy are layered on top of each other, a Location contains a LocationStrategy and a LocationStrategy in turn contains a PlatformLocation. None of them directly exposes the contained entity, i.e. you can't get to the LocationStrategy via the Location API nor to the PlatformLocation via the LocationStrategy.

You'll see many older examples directly accessing PlatformLocation but as its documentation makes clear, this "class should not be used directly by an application developer."

Conclusions

So we started with a confusing array of entities but in the end, it really just boils down to choosing between the DOM provided global location object and the Angular provided Location object. Under certain circumstances, LocationStrategy may also be of interest.

Code

But if you want more insight, why not try out the following code that pulls in every one of the entities that have been mentioned. Look at the console output to see what each entity provides and just experiment with the APIs of each. For simplicity just add this code to one of your existing components:

import { Inject } from '@angular/core';
import { DOCUMENT, Location, LocationStrategy, PlatformLocation } from '@angular/common';

// Normally, you should not access PlatformLocation directly, it's just included here for completeness.
constructor(@Inject(DOCUMENT) private document: Document, private location: Location, private locationStrategy: LocationStrategy, private plaformLocation: PlatformLocation) { }

ngOnInit(): void {
    // These are just different ways to get the same thing, so if this
    // is what want, you might as well use plain location directly.
    console.log('DOM location', location)
    console.log('DOM window.location', window.location)
    console.log('DOM document.location', document.location)
    console.log('Injected document.location', this.document.location)

    // These are layered on top of each other. A Location contains a
    // LocationStrategy and a LocationStrategy contains a PlatformLocation.
    // Note that this.location, used here, is a different thing to plain location above.
    console.log('location', this.location)
    console.log('locationStrategy', this.locationStrategy)
    console.log('platformLocation', this.plaformLocation) // PlatformLocation "should not be used directly by an application developer."
}

Open your app in a browser and look at the console output in developer tools and see if you find what you're looking for.

Note: things become stale quickly in the Angular world - the above all worked fine with Angular 9.

Base href and Location

If you have a simple application with no routes and you've set the base href to something other than / then you may find that functions like prepareExternalUrl fail to take the base href into account. This happens if you haven't included a RouterModule in the imports section of your app.module.ts. For whatever reason, the LocationStrategy and PlatformLocation, that underly Location, are only properly configured if a RouterModule is imported. To get around this, just add the following:

imports: [
  ...
  RouterModule.forRoot([]),
  ...
]

Even though you've specified no routes, i.e. passed in [], this will properly configure things to take your base href into account.

APP_BASE_HREF, PlatformLocation and Location

In some examples, you'll see it stated that you have to explicitly configure APP_BASE_HREF in order for things to pick up your base href. E.g. like so in app.module.ts:

providers: [{
  provide: APP_BASE_HREF,
  useFactory: (pl: PlatformLocation) => pl.getBaseHrefFromDOM(),
  deps: [PlatformLocation]
}]

This may have been necessary at some stage but the current PathLocationStrategy code does this for you automatically, i.e. if you don't set APP_BASE_HREF then it will itself retrieve the base href value using the getBaseHrefFromDOM() method of PathLocationStrategy. You can see this here in the constructor logic of PathLocationStrategy.

Solution 2:

No need for angular specific features, window.location.origin will do it for you.

Solution 3:

console.log(location);

console.log(location.href);

to get base url : console.log(location.origin);

Solution 4:

This doesn't work for me (Angular 7):

this.location.path.name

But I found that it's possible to get it from document:

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

constructor(@Inject(DOCUMENT) private document: Document) {
    const origin = this.document.location.origin;
}