The constructors for the Api classes in typescript-angular2 currently have the definition:
constructor(protected http: Http, @Optional() basePath: string)
To be able to provide a value and have DI use this value, would it be better to set this up as:
constructor(protected http: Http, @Optional()@Inject(BASE_PATH) basePath: string)
And define a variables file with:
export const BASE_PATH = new OpaqueToken('basePath');
And then this could be utilised on app bootstrap by:
Import { BASE_PATH } from './service/variables';
bootstrap(AppComponent, [
{ provide: BASE_PATH, useValue: 'http://myservice:5000' }
]);
2.2.0
I'd be happy to make the contribution via a PR, just checking that there is no prior agreed way. And that this would be an appropriate way to handle this case?
PR merged into master. Please pull the latest master for this enhancement.
in this scenario how would you provide a BASE_PATH for multiple API's ? for example if you had a authentication web api and a appdata api that lived on different servers.
@wdunn001 I've thought I might come up against this same problem and am not sure how to make it work at the moment. I know with angular 4.x OpaqueToken was deprecated in favour of InjectionToken<?> so maybe that has some added functionality that could be used.
Happy to have anyone else with some thoughts on this problem...
@wdunn001
I used the following way of "renaming" to provide two BASE_PATH:
.....
import { BASE_PATH as StorageUrl } from './services/storageApi/variables';
import { BASE_PATH as CalculationUrl } from './services/calculationApi/variables';
@NgModule({
declarations: [...],
imports: [...],
bootstrap: [AppComponent],
providers: [
{ provide: StorageUrl, useValue: 'http://localhost:8080' },
{ provide: CalculationUrl, useValue: 'http://localhost:8090' }
]
@einStefan how does this work? wouldnt the second instance of provider just rename both BASE_PATH vars?
@wdunn001
I found this feature in the TypeScript documentation. (look for "Import a single export from a module" section at: https://www.typescriptlang.org/docs/handbook/modules.html)
Don't know how it works, sorry.
I'm using it as described above and it works for my project.
@damienpontifex InjectionToken<?> doesn't change how the injector works, but it does add type information, so when you use the provider you get some type checking.
With regards to having two BASE_URLs, Angular uses Hierarchial Injectors, which essentially means it tries to use the nearest parent for injecting a value/component. So one of the ways to solve this issue is to have the API provided by different modules, each module providing a different BASE_URL.
I'm surprised to see @einStefan 's example working, because I don't know how the generated API would know to ask for the StorageUrl to be injected. I'm going to try to see if I can replicate. Can you show us a snippet of one of your API classes?
@iblocks-Xander, @wdunn001
After some googeling i have learned what I'm using there :).
It is possible to use an alias for the Import.
It seems to be a JavaScript Feature which is described here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
Here is another example:
http://stackoverflow.com/a/39610348/2753886
@einStefan
Your example works due to having two APIs (And two BASE_PATH objects) I think. If you tried to alias the same BASE_PATH, it is still referring to the same OpaqueToken Object.
The injection points in the generated APIs aren't referring to the aliases, so they will just inject the OpaqueToken value.
When I tried to reproduce with a minimal example, the BASE_PATH injected depended on which one had been last provided (In this example BASE_PATH has a value of "localhost")
// app.module.ts
...
import {BASE_PATH as t1 } from './gen/variables';
import {BASE_PATH as t2 } from './gen/variables';
...
providers: [{
provide: t1,
useValue: "unlocalhost"
},{
provide: t2,
useValue: "localhost"
}]
Looking at your example again, I think your example works because there are actually two BASE_PATH objects, so I imagine in your classes you import a specific BASE_PATH by specifying the directory.
If you had one API that you would like to specify multiple BASE_PATHs for, I think you would have to do this differently. Although, I suppose having different BASE_PATHs for a single API is unlikely!
Most helpful comment
@wdunn001
I used the following way of "renaming" to provide two BASE_PATH: