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?
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?
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.
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;
}
}
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;
}
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' );
}
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`;
};
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
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
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.
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
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;
}
}
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.