Get domain name for service in Angular2

Angular

Angular 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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPavel KulikovView Question on Stackoverflow
Solution 1 - AngularM.E.View Answer on Stackoverflow
Solution 2 - AngularThibsView Answer on Stackoverflow
Solution 3 - AngularGiovanni BassiView Answer on Stackoverflow
Solution 4 - AngularMarfuView Answer on Stackoverflow
Solution 5 - AngulargianlucaparadiseView Answer on Stackoverflow
Solution 6 - AngularNilesh GView Answer on Stackoverflow
Solution 7 - AngularLJHView Answer on Stackoverflow
Solution 8 - AngularLucas SuarezView Answer on Stackoverflow
Solution 9 - AngularbaloozyView Answer on Stackoverflow