2017-04-03 62 views
23

我想添加一个App Settings部分到我的应用程序,它将包含一些常量和预定义的值。App.settings - 角度的方式?

我已阅读this answer其中使用OpaqueToken但它已在Angular中弃用。这article解释的差异,但它没有提供一个完整的例子,我的尝试是不成功的。

这里是我试过(我不知道这是否是正确的方式):

//ServiceAppSettings.ts 

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

const CONFIG = { 
    apiUrl: 'http://my.api.com', 
    theme: 'suicid-squad', 
    title: 'My awesome app' 
}; 
const FEATURE_ENABLED = true; 
const API_URL = new InjectionToken<string>('apiUrl'); 

而这正是我想用这些consts组件:

//MainPage.ts 

import {...} from '@angular/core' 
import {ServiceTest} from "./ServiceTest" 

@Component({ 
    selector: 'my-app', 
    template: ` 
    <span>Hi</span> 
    ` , providers: [ 
    { 
     provide: ServiceTest, 
     useFactory: (apiUrl) => { 
     // create data service 
     }, 
     deps: [ 

     new Inject(API_URL) 
     ] 
    } 
    ] 
}) 
export class MainPage { 


} 

但它不起作用,我得到错误。

问:

我怎么能消费 “app.settings” 的价值观的角度呢?

plunker

NB当然,我可以创造注射服务,并把它放在NgModule的供应商,但正如我说我想InjectionToken,角度的方式来做到这一点。

+0

你可以检查我的答案[这里](http://stackoverflow.com/questions/34986922/ define-global-constants-in-angular-2/43439599#43439599)基于当前官方文档 – JavierFuentes

+0

@ javier no。如果两个供应商提供相同的名称,则您的链接有问题,因此您现在有问题。 Entring opaquetoken –

+0

你知道[OpaqueToken已被弃用]。 (https://angular.io/api/core/OpaqueToken)[本文](https://blog.thoughtram.io/angular/2016/05/23/opaque-tokens-in-angular-2.html )谈到如何防止角提供商名称冲突 – JavierFuentes

回答

24

我想通了如何与InjectionTokens做到这一点(见下面的例子),如果你的项目是使用内置的Angular CLI您可以使用/environments中发现的环境文件静态application wide settings像一个API端点,但根据您的项目因为环境文件只是对象文字,而使用InjectionToken的可注入配置可以使用环境变量,并且由于它是一个类,可以根据应用程序中的其他因素对其应用逻辑进行配置,如初始http请求数据,子域等。

注入令牌示例

/app/app-config.module.ts

import { NgModule, InjectionToken } from '@angular/core'; 
import { environment } from '../environments/environment'; 

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

export class AppConfig { 
    apiEndpoint: string; 
} 

export const APP_DI_CONFIG: AppConfig = { 
    apiEndpoint: environment.apiEndpoint 
}; 

@NgModule({ 
    providers: [{ 
    provide: APP_CONFIG, 
    useValue: APP_DI_CONFIG 
    }] 
}) 
export class AppConfigModule { } 

/app/app.module.ts

import { BrowserModule } from '@angular/platform-browser'; 
import { NgModule } from '@angular/core'; 

import { AppConfigModule } from './app-config.module'; 

@NgModule({ 
    declarations: [ 
    // ... 
    ], 
    imports: [ 
    // ... 
    AppConfigModule 
    ], 
    bootstrap: [AppComponent] 
}) 
export class AppModule { } 

现在你只需DI它到任何组件,服务等:

/app/core/auth.service.ts

import { Injectable, Inject } from '@angular/core'; 
import { Http, Response } from '@angular/http'; 
import { Router } from '@angular/router'; 
import { Observable } from 'rxjs/Observable'; 
import 'rxjs/add/operator/map'; 
import 'rxjs/add/operator/catch'; 
import 'rxjs/add/observable/throw'; 

import { APP_CONFIG, AppConfig } from '../app-config.module'; 
import { AuthHttp } from 'angular2-jwt'; 

@Injectable() 
export class AuthService { 

    constructor(
    private http: Http, 
    private router: Router, 
    private authHttp: AuthHttp, 
    @Inject(APP_CONFIG) private config: AppConfig 
) { } 

    /** 
    * Logs a user into the application. 
    * @param payload 
    */ 
    public login(payload: { username: string, password: string }) { 
    return this.http 
     .post(`${this.config.apiEndpoint}/login`, payload) 
     .map((response: Response) => { 
     const token = response.json().token; 
     sessionStorage.setItem('token', token); // TODO: can this be done else where? interceptor 
     return this.handleResponse(response); // TODO: unset token shouldn't return the token to login 
     }) 
     .catch(this.handleError); 
    } 

    // ... 
} 

然后,您也可以使用导出的AppConfig键入检查配置。

+0

不,但您可以将第一部分复制并粘贴到文件中,将其导入到您的app.module.ts文件中,然后将其输入到任意位置并将其输出到控制台。我会花更长的时间来设置这个蹲在那里,然后它会做这些步骤。 – mtpultz

+0

哦,我以为你已经有一个这样的运动员:-)谢谢。 –

+0

对于那些想要:https://plnkr.co/edit/2YMZk5mhP1B4jTgA37B8?p=preview –

70

如果使用,还有另一种选择:

角CLI提供环境文件src/environments(默认设置会被environment.ts(DEV)和environment.prod.ts(生产))。

请注意,您需要提供所有environment.*文件中的配置参数,例如,

environment.ts

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

environment.prod.ts

export const environment = { 
    production: true, 
    apiEndpoint: '__your_production_server__' 
}; 

并在您的服务中使用它们(正确的环境文件是自动选择):

api.service.ts

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

@Injectable() 
export class ApiService {  

    public apiRequest(): Observable<MyObject[]> { 
    const path = environment.apiEndpoint + `/objects`; 
    // ... 
    } 

// ... 
} 
+2

这应该是个很好的答案;) – Deunz

+0

这是一个简单而优雅的解决方案。谢谢@tilo –

+0

其工作正常。但移动构建时,它也改变为bundle.I应改变我的服务器配置不在代码中后移到生产 – kamalav

0

这里是我的解决方案,从以.json负载允许修改,而不必重建

import { Injectable, Inject } from '@angular/core'; 
import { Http } from '@angular/http'; 
import { Observable } from 'rxjs/Observable'; 
import { Location } from '@angular/common'; 

@Injectable() 
export class ConfigService { 

    private config: any; 

    constructor(private location: Location, private http: Http) { 
    } 

    async apiUrl(): Promise<string> { 
     let conf = await this.getConfig(); 
     return Promise.resolve(conf.apiUrl); 
    } 

    private async getConfig(): Promise<any> { 
     if (!this.config) { 
      this.config = (await this.http.get(this.location.prepareExternalUrl('/assets/config.json')).toPromise()).json(); 
     } 
     return Promise.resolve(this.config); 
    } 
} 

和config.json

{ 
    "apiUrl": "http://localhost:3000/api" 
}