Подтвердить что ты не робот

Определение глобальных констант в Angular 2

В Angular 1.x вы можете определить константы следующим образом:

angular.module('mainApp.config', [])
.constant('API_ENDPOINT', 'http://127.0.0.1:6666/api/')

Что было бы эквивалентно в Angular2 (с Typescript)? Я просто не хочу повторять URL-адрес базы API снова и снова во всех моих сервисах.

4b9b3361

Ответ 1

Ниже меняются изменения для меня на Angular 2 финальной версии:

export class AppSettings {
   public static API_ENDPOINT='http://127.0.0.1:6666/api/';
}

И затем в сервисе:

import {Http} from 'angular2/http';
import {Message} from '../models/message';
import {Injectable} from 'angular2/core';
import {Observable} from 'rxjs/Observable';
import {AppSettings} from '../appSettings';
import 'rxjs/add/operator/map';

@Injectable()
export class MessageService {

    constructor(private http: Http) { }

    getMessages(): Observable<Message[]> {
        return this.http.get(AppSettings.API_ENDPOINT+'/messages')
            .map(response => response.json())
            .map((messages: Object[]) => {
                return messages.map(message => this.parseData(message));
            });
    }

    private parseData(data): Message {
        return new Message(data);
    }
}

Ответ 2

Решение для конфигурации, предоставляемой самой угловой командой, можно найти здесь.

Вот весь соответствующий код:

1) app.config.ts

import { OpaqueToken } from "@angular/core";

export let APP_CONFIG = new OpaqueToken("app.config");

export interface IAppConfig {
    apiEndpoint: string;
}

export const AppConfig: IAppConfig = {    
    apiEndpoint: "http://localhost:15422/api/"    
};

2) app.module.ts

import { APP_CONFIG, AppConfig } from './app.config';

@NgModule({
    providers: [
        { provide: APP_CONFIG, useValue: AppConfig }
    ]
})

3) your.service.ts

import { APP_CONFIG, IAppConfig } from './app.config';

@Injectable()
export class YourService {

    constructor(@Inject(APP_CONFIG) private config: IAppConfig) {
             // You can use config.apiEndpoint now
    }   
}

Теперь вы можете вставлять конфиг везде без использования имен строк и с использованием вашего интерфейса для статических проверок.

Разумеется, вы можете разделить интерфейс и константу дальше, чтобы иметь возможность поставлять различные значения в производстве и разработке, например

Ответ 3

В Angular2 у вас есть следующее обеспечить определение, которое позволяет вам устанавливать различные зависимости:

provide(token: any, {useClass, useValue, useExisting, useFactory, deps, multi}

Сравнение с Angular 1

app.service в Angular1 эквивалентно useClass в Angular2.

app.factory в Angular1 эквивалентно useFactory в Angular2.

app.constant и app.value было упрощено до useValue с меньшими ограничениями. то есть больше блока config.

app.provider - В Angular 2 нет эквивалента.

<сильные > Примеры

Для установки с помощью инжектора корня:

bootstrap(AppComponent,[provide(API_ENDPOINT, { useValue='http://127.0.0.1:6666/api/' })]);

Или настроить с помощью инжектора компонентов:

providers: [provide(API_ENDPOINT, { useValue: 'http://127.0.0.1:6666/api/'})]

provide является короткой рукой для:

var injectorValue = Injector.resolveAndCreate([
  new Provider(API_ENDPOINT, { useValue: 'http://127.0.0.1:6666/api/'})
]);

С инжектором получение значения легко:

var endpoint = injectorValue.get(API_ENDPOINT);

Ответ 4

В Angular 4 вы можете использовать класс среды, чтобы сохранить все ваши глобальные переменные.

По умолчанию у вас есть environment.ts и environment.prod.ts.

Например

export const environment = {
  production: false,
  apiUrl: 'http://localhost:8000/api/'
};

И затем на вашем сервисе:

import { environment } from '../../environments/environment';
...
environment.apiUrl;

Ответ 5

Хотя подход с наличием класса AppSettings со строковой константой как ApiEndpoint работает, он не идеален, так как мы не смогли бы поменять эту реальную ApiEndpoint на некоторые другие значения во время модульного тестирования.

Нам нужно иметь возможность вводить эти конечные точки api в наши сервисы (подумайте о том, чтобы вводить услугу в другую службу). Для этого нам также не нужно создавать целый класс, все, что мы хотим сделать, - это ввести строку в наши сервисы, являющиеся нашей ApiEndpoint. Чтобы закончить отличный ответ на pixelbits, вот полный код о том, как это можно сделать в Angular 2:

Сначала нам нужно сообщить Angular, как предоставить экземпляр нашей ApiEndpoint, когда мы попросим его в нашем приложении (подумайте об этом как о регистрации зависимости):

bootstrap(AppComponent, [
        HTTP_PROVIDERS,
        provide('ApiEndpoint', {useValue: 'http://127.0.0.1:6666/api/'})
]);         


И затем в сервисе вставьте эту ApiEndpoint в конструктор службы и Angular предоставит ее нам на основании нашей регистрации выше:

import {Http} from 'angular2/http';
import {Message} from '../models/message';
import {Injectable, Inject} from 'angular2/core';  // * We import Inject here
import {Observable} from 'rxjs/Observable';
import {AppSettings} from '../appSettings';
import 'rxjs/add/operator/map';

@Injectable()
export class MessageService {

    constructor(private http: Http, 
                @Inject('ApiEndpoint') private apiEndpoint: string) { }

    getMessages(): Observable<Message[]> {
        return this.http.get(`${this.apiEndpoint}/messages`)
            .map(response => response.json())
            .map((messages: Object[]) => {
                return messages.map(message => this.parseData(message));
            });
    } 
    // the rest of the code...
}

Ответ 6

Обновлено для Angular 4+

Теперь мы можем просто использовать файл окружения, который по умолчанию задает угловое значение, если ваш проект генерируется с помощью углового кли.

например

В папке среды создайте следующие файлы

  • environment.prod.ts
  • environment.qa.ts
  • environment.dev.ts

и каждый файл может содержать связанные изменения кода, такие как:

  • environment.prod.ts

    export const environment = {
         production: true,
         apiHost: 'https://api.somedomain.com/prod/v1/',
         CONSUMER_KEY: 'someReallyStupidTextWhichWeHumansCantRead', 
         codes: [ 'AB', 'AC', 'XYZ' ],
    };
    
  • environment.qa.ts

    export const environment = {
         production: false,
         apiHost: 'https://api.somedomain.com/qa/v1/',
         CONSUMER_KEY : 'someReallyStupidTextWhichWeHumansCantRead', 
         codes: [ 'AB', 'AC', 'XYZ' ],
    };
    
  • environment.dev.ts

    export const environment = {
         production: false,
         apiHost: 'https://api.somedomain.com/dev/v1/',
         CONSUMER_KEY : 'someReallyStupidTextWhichWeHumansCantRead', 
         codes: [ 'AB', 'AC', 'XYZ' ],
    };
    

Случай использования в приложении

Вы можете импортировать среды в любой файл, такие как услуги clientUtilServices.ts

import {environment} from '../../environments/environment';

getHostURL(): string {
    return environment.apiHost;
  }

Вариант использования в сборке

Откройте свой угловой файл .angular-cli.json и внутри "apps": [{...}] добавьте следующий код

 "apps":[{
        "environments": {
            "dev": "environments/environment.ts",
            "prod": "environments/environment.prod.ts",
            "qa": "environments/environment.qa.ts",
           }
         }
       ]

Если вы хотите построить для производства, запустите ng build --env=prod он будет читать конфигурацию из environment.prod.ts, так же, как вы можете сделать это для qa или dev

## Старый ответ

Я делал что-то вроде ниже, у моего провайдера:

import {Injectable} from '@angular/core';

@Injectable()
export class ConstantService {

API_ENDPOINT :String;
CONSUMER_KEY : String;

constructor() {
    this.API_ENDPOINT = 'https://api.somedomain.com/v1/';
    this.CONSUMER_KEY = 'someReallyStupidTextWhichWeHumansCantRead'
  }
}

Затем у меня есть доступ ко всем постоянным данным в любом месте

import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/add/operator/map';

import {ConstantService} from  './constant-service'; //This is my Constant Service


@Injectable()
export class ImagesService {
    constructor(public http: Http, public ConstantService: ConstantService) {
    console.log('Hello ImagesService Provider');

    }

callSomeService() {

    console.log("API_ENDPOINT: ",this.ConstantService.API_ENDPOINT);
    console.log("CONSUMER_KEY: ",this.ConstantService.CONSUMER_KEY);
    var url = this.ConstantService.API_ENDPOINT;
    return this.http.get(url)
  }
 }

Ответ 7

Это мой недавний опыт в этом сценарии:

  • @angular/cli: 1.0.0
  • node: 6.10.2
  • @angular/core: 4.0.0

Я следил за официальными и обновленными документами здесь:

https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#dependency-injection-tokens

Кажется, что OpaqueToken теперь устарел, и мы должны использовать InjectionToken, поэтому это мои файлы, работающие как обаяние:

app-config.interface.ts

export interface IAppConfig {

  STORE_KEY: string;

}

app-config.constants.ts

import { InjectionToken } from "@angular/core";
import { IAppConfig } from "./app-config.interface";

export const APP_DI_CONFIG: IAppConfig = {

  STORE_KEY: '[email protected][email protected]'

};

export let APP_CONFIG = new InjectionToken< IAppConfig >( 'app.config' );

app.module.ts

import { APP_CONFIG, APP_DI_CONFIG } from "./app-config/app-config.constants";

@NgModule( {
  declarations: [ ... ],
  imports: [ ... ],
  providers: [
    ...,
    {
      provide: APP_CONFIG,
      useValue: APP_DI_CONFIG
    }
  ],
  bootstrap: [ ... ]
} )
export class AppModule {}

my-service.service.ts

  constructor( ...,
               @Inject( APP_CONFIG ) private config: IAppConfig) {

    console.log("This is the App Key: ", this.config.STORE_KEY);
    //> This is the App Key:  [email protected][email protected]

  }

Результат чист и нет предупреждений на консоли, благодаря недавнему комментарию Джона Папа в этом выпуске:

https://github.com/angular/angular-cli/issues/2034

Ключ был реализован в другом файле интерфейса.

Ответ 8

Все решения кажутся сложными. Я ищу простейшее решение для этого случая, и я просто хочу использовать константы. Константы просты. Есть ли что-нибудь, что говорит против следующего решения?

app.const.ts

'use strict';

export const dist = '../path/to/dist/';

app.service.ts

import * as AppConst from '../app.const'; 

@Injectable()
export class AppService {

    constructor (
    ) {
        console.log('dist path', AppConst.dist );
    }

}

Ответ 9

Просто используйте константу Typescript

export var API_ENDPOINT = 'http://127.0.0.1:6666/api/';

Вы можете использовать его в инжекторе зависимостей, используя

bootstrap(AppComponent, [provide(API_ENDPOINT, {useValue: 'http://127.0.0.1:6666/api/'}), ...]);

Ответ 10

Если вы используете Webpack, который я рекомендую, вы можете настроить константы для разных сред. Это особенно ценно, когда у вас есть разные постоянные значения для каждой среды.

Вероятно, в вашем каталоге /config (например, webpack.dev.js, webpack.prod.js и т.д.), вероятно, будет несколько файлов в Интернете. Тогда у вас будет custom-typings.d.ts, вы добавите их туда. Вот общий шаблон для каждого файла и пример использования в компоненте.

WebPack. {ENV}.js

const API_URL = process.env.API_URL = 'http://localhost:3000/';
const JWT_TOKEN_NAME = "id_token";
...
    plugins: [
      // NOTE: when adding more properties, make sure you include them in custom-typings.d.ts
      new DefinePlugin({
        'API_URL': JSON.stringify(API_URL),
        'JWT_TOKEN_NAME': JSON.stringify(JWT_TOKEN_NAME)
      }),

Custom-typings.d.ts

declare var API_URL: string;
declare var JWT_TOKEN_NAME: string;
interface GlobalEnvironment {
  API_URL: string;
  JWT_TOKEN_NAME: string;
}

Компонент

export class HomeComponent implements OnInit {
  api_url:string = API_URL;
  authToken: string = "Bearer " + localStorage.getItem(JWT_TOKEN_NAME)});
}

Ответ 11

Использование файла свойств, созданного во время сборки, является простым и легким. Это подход, который использует CLI Angular. Определите файл свойств для каждой среды и используйте команду во время сборки, чтобы определить, какой файл будет скопирован в ваше приложение. Затем просто импортируйте файл свойств для использования.

https://github.com/angular/angular-cli#build-targets-and-environment-files

Ответ 12

Один подход для Angular4 будет определять константу на уровне модуля:

const api_endpoint = 'http://127.0.0.1:6666/api/';

@NgModule({
  declarations: [AppComponent],
  bootstrap: [AppComponent],
  providers: [
    MessageService,
    {provide: 'API_ENDPOINT', useValue: api_endpoint}
  ]
})
export class AppModule {
}

Затем, в вашем сервисе:

import {Injectable, Inject} from '@angular/core';

@Injectable()
export class MessageService {

    constructor(private http: Http, 
      @Inject('API_ENDPOINT') private api_endpoint: string) { }

    getMessages(): Observable<Message[]> {
        return this.http.get(this.api_endpoint+'/messages')
            .map(response => response.json())
            .map((messages: Object[]) => {
                return messages.map(message => this.parseData(message));
            });
    }

    private parseData(data): Message {
        return new Message(data);
    }
}

Ответ 13

AngularJS module.constant не определяет константу в стандартном смысле.

В то время как он сам по себе является механизмом регистрации провайдера, его лучше понимать в контексте связанной функции module.value ($provide.value). В официальной документации четко указывается пример использования:

Зарегистрируйте службу значений с помощью $injector, например строки, числа, массива, объекта или функции. Это коротко для регистрации службы, где его свойство $get является функцией factory, которая не принимает аргументов и возвращает службу значений. Это также означает, что нельзя вводить другие службы в службу стоимости.

Сравните это с документацией для module.constant ($provide.constant), в которой также четко указывается прецедент (основное внимание):

Зарегистрируйте постоянную службу с помощью инжектора $, например строки, числа, массива, объекта или функции. Как и значение, невозможно добавить другие службы в константу. Но в отличие от значения константа может быть введена в конфигурационную функцию модуля (см. angular.Module), и она не может быть переопределена декорером AngularJS.

Следовательно, функция AngularJS constant не дает константы в общепринятом значении термина в поле.

Тем не менее, ограничения, помещенные на предоставленный объект, вместе с его более ранней доступностью через $injector, явно указывают на то, что имя используется по аналогии.

Если вам нужна фактическая константа в приложении AngularJS, вы будете "предоставлять" один и тот же путь, который вы бы использовали в любой программе JavaScript, которая

export const π = 3.14159265;

В Angular 2 применяется тот же метод.

Angular 2 приложения не имеют фазы конфигурации в том же смысле, что и приложения AngularJS. Кроме того, нет механизма декоратора обслуживания (AngularJS Decorator), но это не особенно удивительно, учитывая, насколько они отличаются друг от друга.

Пример

angular
  .module('mainApp.config', [])
  .constant('API_ENDPOINT', 'http://127.0.0.1:6666/api/');

является неопределенно произвольным и слегка отложенным, потому что $provide.constant используется для указания объекта, который, кстати, также является константой. Вы могли бы также написать

export const apiEndpoint = 'http://127.0.0.1:6666/api/';

для всех может измениться.

Теперь аргумент для проверяемости, издеваясь над константой, уменьшается, потому что он буквально не изменяется.

Никто не издевается над π.

Конечно, семантика вашей конкретной заявки может заключаться в том, что ваша конечная точка может измениться, или ваш API может иметь непрозрачный механизм переключения на отказ, поэтому было бы разумно, чтобы конечная точка API изменилась при определенных обстоятельствах.

Но в этом случае предоставление его в виде строкового литерала одного URL-адреса для функции constant не сработало бы.

Хороший аргумент и, вероятно, еще один, связанный с причиной существования функции AngularJS $provide.constant, заключается в том, что, когда AngularJS был введен, JavaScript не имел стандартной концепции модуля. В этом случае глобальные переменные будут использоваться для обмена значениями, изменяемыми или неизменяемыми, а использование глобальных переменных проблематично.

Тем не менее, предоставление чего-то подобного через рамки увеличивает связь с этой структурой. Он также смешивает специфическую логику Angular с логикой, которая будет работать в любой другой системе.

Это не значит, что это неправильный или вредный подход, но лично, если я хочу константу в приложении Angular 2, я напишу

export const π = 3.14159265;

так же, как и я, используя AngularJS.

Чем больше изменений...

Ответ 14

Вы можете создать класс для своей глобальной переменной, а затем экспортировать этот класс следующим образом:

export class CONSTANT {
    public static message2 = [
        { "NAME_REQUIRED": "Name is required" }
    ]

    public static message = {
        "NAME_REQUIRED": "Name is required",
    }
}

После создания и экспорта класса CONSTANT вам следует импортировать этот класс в том классе, где вы хотите использовать, например:

import { Component, OnInit                       } from '@angular/core';
import { CONSTANT                                } from '../../constants/dash-constant';


@Component({
  selector   : 'team-component',
  templateUrl: `../app/modules/dashboard/dashComponents/teamComponents/team.component.html`,
})

export class TeamComponent implements OnInit {
  constructor() {
    console.log(CONSTANT.message2[0].NAME_REQUIRED);
    console.log(CONSTANT.message.NAME_REQUIRED);
  }

  ngOnInit() {
    console.log("oninit");
    console.log(CONSTANT.message2[0].NAME_REQUIRED);
    console.log(CONSTANT.message.NAME_REQUIRED);
  }
}

Вы можете использовать это либо в constructor, либо ngOnInit(){}, либо в любых предопределенных методах.

Ответ 15

Лучший способ создать широкие константы приложения в Angular 2 - это использовать файлы environment.ts. Преимущество объявления таких констант состоит в том, что вы можете изменять их в зависимости от среды, поскольку для каждой среды может быть другой файл среды.