Nice programing

App.settings-Angular 방식?

nicepro 2020. 12. 2. 21:55
반응형

App.settings-Angular 방식?


App Settings일부 const 및 사전 정의 된 값을 포함 섹션을 내 앱 에 추가하고 싶습니다 .

나는 이미 사용하는 이 답변읽었 OpaqueToken지만 Angular에서는 더 이상 사용되지 않습니다. 기사 는 차이점을 설명하지만 완전한 예를 제공하지 않았으며 내 시도는 실패했습니다.

다음은 내가 시도한 것입니다 (올바른 방법인지 모르겠습니다) :

//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');

그리고 이것은 내가 그 const를 사용하려는 구성 요소입니다.

//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 {


}

하지만 작동하지 않고 오류가 발생합니다.

질문:

Angular 방식으로 "app.settings"값을 어떻게 사용할 수 있습니까?

플 런커

NB 물론 Injectable 서비스를 생성하여 NgModule 공급자에 넣을 수 있습니다.하지만 제가 말했듯 InjectionToken이 Angular 방식으로 하고 싶습니다 .


InjectionTokens (아래 예제 참조)를 사용하여이 작업을 수행하는 방법을 알아 냈고 프로젝트가를 사용하여 빌드 된 경우 API 엔드 포인트와 같은 정적 Angular CLI환경 파일을 사용할 수 있지만 프로젝트의 요구 사항에 따라 대부분 끝날 것입니다 환경 파일은 객체 리터럴 일 뿐이며 's를 사용 하는 주입 가능한 구성 은 환경 변수를 사용할 수 있으며 클래스이기 때문에 초기 http 요청 데이터, 하위 도메인과 같은 응용 프로그램의 다른 요소를 기반으로 구성하는 논리를 적용 할 수 있습니다. 등/environmentsapplication wide settingsInjectionToken

주입 토큰 예

/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를 사용하여 구성 확인을 입력 할 수도 있습니다.


사용하는 경우 또 다른 옵션이 있습니다.

Angular CLI는 환경 파일을 제공합니다 src/environments(기본 파일 environment.ts(dev) 및 environment.prod.ts(production)).

모든 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`;
    // ...
  }

// ...
}

Github (Angular CLI 버전 6) 또는 공식 Angular 가이드 (버전 7)의 애플리케이션 환경에 대해 자세히 알아보세요 .


environment.*.tsAPI URL 구성에 파일 을 사용하는 것은 바람직하지 않습니다 . 이것은 "환경"이라는 단어를 언급하기 때문에 그렇게해야 할 것 같습니다.

이것을 사용하는 것은 실제로 컴파일 타임 구성 입니다. API URL을 변경하려면 다시 빌드해야합니다. 그것은 당신이하고 싶지 않은 일입니다 ... 친절한 QA 부서에 문의하십시오 :)

필요한 것은 런타임 구성입니다 . 즉, 앱이 시작될 때 구성을로드합니다.

다른 답변은 이것에 대해 다루지 만 차이점은 앱이 시작 되 자마자 구성을로드 해야 할 때마다 일반 서비스에서 사용할 수 있다는 것입니다.

런타임 구성을 구현하려면 :

  1. /src/assets/폴더에 JSON 구성 파일 추가 (빌드시 복사 됨)
  2. AppConfigService구성을로드하고 배포하기 위한 만들기
  3. 다음을 사용하여 구성로드 APP_INITIALISER

1. 구성 파일 추가 /src/assets

다른 폴더에 추가 할 수 있지만 CLI에 angular.json. 자산 폴더를 사용하여 시작하십시오.

{
  "apiBaseUrl": "https://development.local/apiUrl"
}

2. 만들기 AppConfigService

구성 값이 필요할 때마다 삽입되는 서비스입니다.

@Injectable({
  providedIn: 'root'
})
export class AppConfigService {

  private appConfig: any;

  constructor(private http: HttpClient) { }

  loadAppConfig() {
    return this.http.get('/assets/config.json')
      .toPromise()
      .then(data => {
        this.appConfig = data;
      });
  }

  // This is an example property ... you can make it however you want.
  get apiBaseUrl() {

    if (!this.appConfig) {
      throw Error('Config file not loaded!');
    }

    return this.appConfig.apiBaseUrl;
  }
}

3. 다음을 사용하여 구성을로드합니다. APP_INITIALISER

AppConfigService구성이 완전히로드 된 상태에서를 안전하게 삽입 하려면 앱 시작시 구성을로드해야합니다. 중요한 것은 초기화 팩토리 함수가 a를 반환 Promise해야 Angular가 시작을 완료하기 전에 해결이 완료 될 때까지 기다려야한다는 것을 알 수 있습니다.

NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [
    {
      provide: APP_INITIALIZER,
      multi: true,
      deps: [AppConfigService],
      useFactory: (appConfigService: AppConfigService) => {
        return () => {
          //Make sure to return a promise!
          return appConfigService.loadAppConfig();
        };
      }
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

이제 필요한 곳에 삽입 할 수 있으며 모든 구성을 읽을 준비가됩니다.

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit {

  apiBaseUrl: string;

  constructor(private appConfigService: AppConfigService) {}

  ngOnInit(): void {
    this.apiBaseUrl = this.appConfigService.apiBaseUrl;
  }

}

충분히 강력하게 말할 수는 없지만 컴파일 타임 구성이 안티 패턴이므로 API URL을 구성합니다 . 런타임 구성을 사용하십시오.


Here's my solution, loads from .json to allow changes without rebuilding

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);
    }
}

and config.json

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

Here's my two solutions for this

1. Store in json files

Just make a json file and get in your component by $http.get() method. If I was need this very low then it's good and quick.

2. Store by using data services

If you want to store and use in all components or having large usage then it's better to use data service. Like this :

  1. Just create static folder inside src/app folder.

  2. Create a file named as fuels.ts into static folder. You can store other static files here also. Let define your data like this. Assuming you having fuels data.

__

export const Fuels {

   Fuel: [
    { "id": 1, "type": "A" },
    { "id": 2, "type": "B" },
    { "id": 3, "type": "C" },
    { "id": 4, "type": "D" },
   ];
   }
  1. Create a file name static.services.ts

__

import { Injectable } from "@angular/core";
import { Fuels } from "./static/fuels";

@Injectable()
export class StaticService {

  constructor() { }

  getFuelData(): Fuels[] {
    return Fuels;
  }
 }`
  1. Now You can make this available for every module

just import in app.module.ts file like this and change in providers

import { StaticService } from './static.services';

providers: [StaticService]

이제 StaticService모든 모듈 에서처럼 이것을 사용하십시오 .

그게 다야.

참고 URL : https://stackoverflow.com/questions/43193049/app-settings-the-angular-way

반응형