Мне нужно сделать запрос на один и тот же сервер, отдохнуть api на другом порту.
Как я могу сделать это без полного имени hardcoding в служебных URL-адресах?
Мне нужно сделать запрос на один и тот же сервер, отдохнуть api на другом порту.
Как я могу сделать это без полного имени hardcoding в служебных URL-адресах?
Нет необходимости в угловом2-специфичном решении. Вы можете использовать window.location.hostname для получения текущего имени хоста.
Обратите внимание, однако, что если вы не хотите использовать глобальные переменные, такие как window -object напрямую, вы можете предоставить свой собственный объект Window, который затем можно внедрить.
См. Этот полный рабочий образец углового Stackblitz для деталей.
Как уже говорили другие, оригинальный ответ больше не работает. Для Angular 6+ необходимо предоставить токен впрыска, чтобы window -object можно было разрешить и в AOT -build.
Я рекомендую создать массив WINDOW_PROVIDERS в отдельном файле, например:
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
]
Константу WINDOW_PROVIDERS можно добавить в массив providers в AppModule следующим образом:
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [
WINDOW_PROVIDERS, // <- add WINDOW_PROVIDERS here
SampleService,
],
bootstrap: [AppComponent]
})
export class AppModule { }
В SampleService window объект может быть внедрен с использованием определенного токена инъекции следующим образом:
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;
}
}
Поэтому вам нужно установить провайдера для Window -object при загрузке вашего приложения.
import {provide} from 'angular2/core';
bootstrap(..., [provide(Window, {useValue: window})]);
После этого вы можете использовать объект окна и получить доступ к имени хоста следующим образом:
constructor(private window: Window) {
var hostname = this.window.location.hostname;
}
Другой вариант - использовать DOCUMENT из @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 последнее рабочее решение:
app.module.ts
providers: [
{provide: Window, useValue: window},
...
]
youclass.ts
constructor(
@Inject(Window) private _window: Window
) {
this._baseUrl = `http://${this._window.location.hostname}:3333`;
};
Вы можете использовать window, как заявили другие, и чтобы сделать его инъекционным, начиная с ng6 и выше, вам нужен токен инъекции.
Объявите токен так:
export const WINDOW = new InjectionToken('window',
{ providedIn: 'root', factory: () => window }
);
Затем используйте его в конструкторе класса:
class Foo {
constructor(@Inject(WINDOW) private window: Window) { }
}
Поскольку Window - это интерфейс в TypeScript, если вы не сделаете инъекцию подобным образом, при создании проекта для производства вы получите ошибку: Can't resolve all parameters for <ClassName> удается Can't resolve all parameters for <ClassName>. А потом еще: ERROR in: Error: Internal error: unknown identifier undefined.
Чтобы лучше понять инъекцию, прочитайте угловые документы для DI: https://angular.io/guide/dependency-injection
Я достиг этого с помощью следующего кода в 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);
}
}
Это должно печатать имя домена в консоли.
Я рекомендую использовать window.location, как прокомментировали другие.
Однако вы также можете сделать это, импортировав библиотеку Angular common 'Location' и используя ее для инъекции следующим образом:
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;
}
}
Я проверяю это на Angular 7, и он работал правильно
declare var window: any;
console.log (window.location.host); //result lrlucas.github.io > domain github pages
с window.location.host я получаю полный домен
Примечание. @Component переменную окна перед @Component
Это должно помочь вам:
import {LocationStrategy} from '@angular/common';
constructor(private locationStrategy:LocationStrategy) {
console.log(locationStrategy.prepareExternalUrl('xxx'));
}
Я использую простой JavaScript и URL нативного API для анализа URL:
const parsedUrl = new URL(window.location.href);
const baseUrl = parsedUrl.origin;
console.log(baseUrl); // this will print http://example.com or http://localhost:4200