Get domain name for service in Angular2
AngularAngular Problem Overview
I need to make request to same server, REST API on another port.
How can I do this without hardcoding full name in service URLs?
Angular Solutions
Solution 1 - Angular
There's no need for an angular2-specific solution. You can use the window.location.hostname
to get the current hostname.
Note, however, if you don't want to use global variables like the window
-object directly, you can provide your own Window
object, which then can be injected.
See this full working Stackblitz Angular sample for details.
Updated Answer for Angular 6+
As others have stated, the original answer does not work anymore. For Angular 6+, you need to provide an Injection Token, so that the window
-object can be resolved in the AOT-build too.
Otherwise you will get the error "Can't resolve all parameters".
I recommend creating a WINDOW_PROVIDERS
array in a separate file like this:
import { InjectionToken, FactoryProvider } from '@angular/core';
export const WINDOW = new InjectionToken<Window>('window');
const windowProvider: FactoryProvider = {
provide: WINDOW,
useFactory: () => window
};
export const WINDOW_PROVIDERS = [
windowProvider
]
The WINDOW_PROVIDERS
constant can be added to the providers
array in the AppModule
like this:
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [
WINDOW_PROVIDERS, // <- add WINDOW_PROVIDERS here
SampleService,
],
bootstrap: [AppComponent]
})
export class AppModule { }
In the SampleService
, the window
object can be injected by using the defined Injection Token like this:
import { Injectable, Inject } from '@angular/core';
import { WINDOW } from '../window.provider';
@Injectable()
export class SampleService {
constructor(@Inject(WINDOW) private window: Window) {
}
getHostname() : string {
return this.window.location.hostname;
}
}
Original Answer for Angular 2
Therefore you need to set the provider for the Window
-object when bootstrapping your application.
import {provide} from 'angular2/core';
bootstrap(..., [provide(Window, {useValue: window})]);
After that you can use the window object and access the hostname like this:
constructor(private window: Window) {
var hostname = this.window.location.hostname;
}
Solution 2 - Angular
Another option is to use DOCUMENT from @angular/platform-browser.
import {DOCUMENT} from '@angular/platform-browser';
constructor(@Inject(DOCUMENT) private document: Document) {
let url = document.location.protocol +'//'+ document.location.hostname + ':my_port' );
}
Solution 3 - Angular
You can use window
, as others have stated, and to make it injectable, from ng6 and forward, you need an injection token.
Declare the token like this:
export const WINDOW = new InjectionToken('window',
{ providedIn: 'root', factory: () => window }
);
Then use it in the class constructor:
class Foo {
constructor(@Inject(WINDOW) private window: Window) { }
}
As Window
is an interface in TypeScript, if you don't do the injection like that, when you build the project for production you will get an error: Can't resolve all parameters for <ClassName>
.
And later another one: ERROR in : Error: Internal error: unknown identifier undefined
.
To understand injection better, read the angular docs for DI: https://angular.io/guide/dependency-injection
Solution 4 - Angular
Angular 2 latest working solution:
app.module.ts
providers: [
{provide: Window, useValue: window},
...
]
youclass.ts
constructor(
@Inject(Window) private _window: Window
) {
this._baseUrl = `http://${this._window.location.hostname}:3333`;
};
Solution 5 - Angular
I'm using plain javascript and URL native api for URL parsing:
declare var window: any; // Needed on Angular 8+
const parsedUrl = new URL(window.location.href);
const baseUrl = parsedUrl.origin;
console.log(baseUrl); // this will print http://example.com or http://localhost:4200
Solution 6 - Angular
I achieved it with following code in my app.component.ts
:
import { Component, OnInit, Inject, Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
constructor(@Inject(DOCUMENT) private document: any) { }
ngOnInit() {
this.domain = this.document.location.hostname;
console.log(this.domain);
}
}
This should print the domain name in your console.
Solution 7 - Angular
I recommend using window.location
as others have kindly stated.
However, you can also do this by importing Angular's common 'Location' library and using it in an injectable like so:
import { Injectable } from '@angular/core';
import { Location } from '@angular/common';
const otherPort = 8000;
@Injectable()
export class ServiceOrComponentName {
constructor(location: Location) {
this.baseUrl = location._platformStrategy._platformLocation._location.protocol +
'//' + location._platformStrategy._platformLocation._location.hostname +
':' + otherPort;
}
}
Solution 8 - Angular
I test this on Angular 7 and it worked correctly
declare var window: any;
console.log (window.location.host); //result lrlucas.github.io > domain github pages
with window.location.host I get the full domain
Note: Declare the window variable before @Component
Solution 9 - Angular
Just inject Document. Angular has a default implementation for Document. Document has a property called defaultView that has all the goodies like window.
import { DOCUMENT } from '@angular/common';
import { Inject, Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class HostnameService
{
constructor(
@Inject(DOCUMENT) private document: Document
) { }
getHostname(): string
{
// Remember to use this.document as unscoped document also exists but is not mockable.
return this.document.defaultView.window.location.hostname;
// Or use the location on document.
return this.document.location.hostname;
}
}
There is no setup required elsewhere.