简体   繁体   中英

Understanding Angular2 project structure

I'm a bit confused around an typescript/Angular2 project structure I've downloaded as a base code in order to extend it.

It's related with how providers are initialized and provided on angular2.

Currently, this is AppModule code:

import { ENV_PROVIDERS } from './environment';
import { APP_RESOLVER_PROVIDERS } from './app.resolver';

// Application wide providers
const APP_PROVIDERS = [
  ...APP_RESOLVER_PROVIDERS,
  AppState,
  AppConfig
];
@NgModule({
  bootstrap: [ App ],
  declarations: [ ... ],
  imports: [ ... ],
  providers: [
    ENV_PROVIDERS,
    APP_PROVIDERS
  ]
})
export class AppModule {

As you can see there are two items: ENV_PROVIDERS and APP_PROVIDERS provided as an array of providers.

app.resolver.ts :

import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';

@Injectable()
export class DataResolver implements Resolve<any> {
  constructor() {

  }
  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    return Observable.of({ res: 'I am data'});
  }
}

// an array of services to resolve routes with data
export const APP_RESOLVER_PROVIDERS = [
  DataResolver
];

environtment.ts :

// Angular 2
// Environment Providers
let PROVIDERS: any[] = [
  // common env directives
];

if ('production' === ENV) {
  PROVIDERS = [
    ...PROVIDERS,
    // custom providers in production
  ];

} else {
  // Development
  PROVIDERS = [
    ...PROVIDERS,
    // custom providers in development
  ];

}

export const ENV_PROVIDERS = [
  ...PROVIDERS
];

By other hand, I'm using a library which is a REST client implementation. This library has an ApiModule class with a forConfig method I'm not able to figure out how to use it. It's returning an object setting ngModule and providers ...

@NgModule({
  imports:      [ CommonModule, HttpModule ],
  declarations: [],
  exports:      [],
  providers:    [ UsersService ]
})
export class ApiModule {
    public static forConfig(configuration: Configuration): ModuleWithProviders {
        return {
            ngModule: ApiModule,
            providers: [ {provide: Configuration, useValue: configuration}]
        }
    }
}

where Configuration is:

export interface ConfigurationParameters {
    apiKey?: string;
    username?: string;
    password?: string;
    accessToken?: string;
    basePath?: string;
}

export class Configuration {
    apiKey: string;
    username: string;
    password: string;
    accessToken: string;
    basePath: string;


    constructor(configurationParameters: ConfigurationParameters = {}) {
        this.apiKey = configurationParameters.apiKey;
        this.username = configurationParameters.username;
        this.password = configurationParameters.password;
        this.accessToken = configurationParameters.accessToken;
        this.basePath = configurationParameters.basePath;
    }
}

I'd like to know according to this structure how I'm able to add my custom providers and set for example basePath property.

This an example of UserService :

@Injectable()
export class UsersService {
    protected basePath = 'http://localhost/commty/cmng';
    public defaultHeaders: Headers = new Headers();
    public configuration: Configuration = new Configuration();

    constructor(protected http: Http, @Optional()@Inject(BASE_PATH) basePath: string, @Optional() configuration: Configuration) {

I hope I've explained so well.

I see that you are using the typescript-angular2 client for the petstore. I myself love swagger and am happy people are using it!

Anyhow to answer your question if you want to set basePath without having to use that configuration in forConfig you can simply do this

in AppModule:

...
@NgModule({
  bootstrap: [ App ],
  declarations: [ ... ],
  imports: [ ... ],
  providers: [
    ENV_PROVIDERS,
    APP_PROVIDERS,
    {provide: BASE_PATH, useValue: 'http:your.url.awesome'}
  ]
})
export class AppModule {

This will utilize the injected value for all of the modules that use that @Inject keyword which all of the swagger api's do

You could also use this if you are bootstrapping by hand:

in BootstrapFile:

    bootstrap(AppComponent, [
        { provide: BASE_PATH, useValue: 'https://your-web-service.com' },
    ]);

If you want to take advantage of using the configuration object you'd change to this:

import { ApiModule, Configuration } from "module-library-name";
...
const myAppConfig = new Configuration({
 ...
 basePath: 'https://your-web-service.com'
});
@NgModule({
  bootstrap: [ App ],
  declarations: [ 
  ApiModule.forConfig(myAppConfig);
  ],
  imports: [ ... ],
  providers: [ ... ]
})
export class AppModule {

if you wanted to dynamically determine your configuration before the app starts and then pas that along into the app module you'd use a provider for APP_INITIALIZER which I can add if this answer is still needed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM