Reputation: 93
I get this error when i am trying to navigate to a WebApi Controller. This error is what i get as soon as the page loads because the codes are situated in the constructor function.
core.js:1598 ERROR Error: Uncaught (in promise): Error: StaticInjectorError(AppModule)[BASE_URL]:
StaticInjectorError(Platform: core)[BASE_URL]:
NullInjectorError: No provider for BASE_URL!
Error: StaticInjectorError(AppModule)[BASE_URL]:
StaticInjectorError(Platform: core)[BASE_URL]:
NullInjectorError: No provider for BASE_URL!
at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (core.js:979)
at resolveToken (core.js:1232)
at tryResolveToken (core.js:1182)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:1077)
at resolveToken (core.js:1232)
at tryResolveToken (core.js:1182)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:1077)
at resolveNgModuleDep (core.js:9217)
at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (core.js:9911)
at resolveDep (core.js:10276)
at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (core.js:979)
at resolveToken (core.js:1232)
at tryResolveToken (core.js:1182)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:1077)
at resolveToken (core.js:1232)
at tryResolveToken (core.js:1182)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:1077)
at resolveNgModuleDep (core.js:9217)
at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (core.js:9911)
at resolveDep (core.js:10276)
at resolvePromise (zone.js:814)
at resolvePromise (zone.js:771)
at zone.js:873
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
at Object.onInvokeTask (core.js:4053)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188)
at drainMicroTaskQueue (zone.js:595)
login.component.ts
import { Component, Inject } from '@angular/core';
import { NgForm } from '@angular/forms';
import { Router, ActivatedRoute } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { Candidates } from '/Solutions/Angular/ExamBuddy/Interfaces/Candidate';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent {
candDetails: Candidates;
constructor(private http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
var url = baseUrl + '/api/Candidate/ExamDetails/12345';
this.http.get<Candidates>(url).subscribe(result => { this.candDetails = result; }, error => console.error(error));
}
This is also my app.module.ts code.
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { ExamComponent } from './exam/exam.component';
import { LoginComponent } from './login/login.component';
// import { RouterModule } from '@angular/router';
import { InstructionComponent } from './instruction/instruction.component';
import { routes } from './app.route';
@NgModule({
declarations: [
AppComponent,
ExamComponent,
LoginComponent,
InstructionComponent,
],
imports: [
BrowserModule,
HttpClientModule,
FormsModule,
routes
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
i also have the WebApi controller which connects to the database and fetches the result in JSON format.
Upvotes: 2
Views: 8378
Reputation: 7357
In my case I tried to enable Hot Module Replacement. The official instructions for HMR have this example for main.ts
:
Update src/main.ts to use the file we just created:
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
import { hmrBootstrap } from './hmr';
if (environment.production) {
enableProdMode();
}
const bootstrap = () => platformBrowserDynamic().bootstrapModule(AppModule);
if (environment.hmr) {
if (module[ 'hot' ]) {
hmrBootstrap(module, bootstrap);
} else {
console.error('HMR is not enabled for webpack-dev-server!');
console.log('Are you using the --hmr flag for ng serve?');
}
} else {
bootstrap().catch(err => console.log(err));
}
(https://github.com/angular/angular-cli/wiki/stories-configure-hmr)
However, the Visual Studio 2017 ASP.Net Core Angular CLI template includes these lines:
const providers = [
{ provide: 'BASE_URL', useFactory: getBaseUrl, deps: [] }
];
platformBrowserDynamic(providers).bootstrapModule(AppModule)
.catch(err => console.log(err));
Notice that the providers
array is not being passed into the HMR main.ts
example. The simple fix is to simply pass it in to platformBrowserDynamic
. The corrected line then looks like this:
const providers = [
{ provide: 'BASE_URL', useFactory: getBaseUrl, deps: [] }
];
const bootstrap = () => platformBrowserDynamic(providers).bootstrapModule(AppModule);
Upvotes: 0
Reputation: 39
First: In main.ts, I have the following code, which refers to index.html
export function getBaseUrl() {
return document.getElementsByTagName('base')[0].href;
}
const providers = [
{ provide: 'BASE_URL', useFactory: getBaseUrl, deps: [] }
];
platformBrowserDynamic(providers).bootstrapModule(AppModule)
.catch(err => console.log(err));
Second: In our component (fetch-data.component.ts), we use the BASE_URL in the following way:
export class FetchDataComponent {
public forecasts: WeatherForecast[];
constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
http.get<WeatherForecast[]>(baseUrl + 'api/SampleData/WeatherForecasts').subscribe(result => {
this.forecasts = result;
}, error => console.error(error));
}
}
that's it.
Upvotes: 4
Reputation: 96
You are injecting a string value with the key BASE_URL
in your LoginComponent
, with the inject decorator: @Inject('BASE_URL') baseUrl: string
. For this to work you need to provide a value for BASE_URL
in your AppModule. But you didn't provide a vaule, this is what the error is telling you: NullInjectorError: No provider for BASE_URL!
In Angular 5 it is recommended to create InjectionToken
e.g.
import { InjectionToken } from '@angular/core';
export const BASE_URL = new InjectionToken<string>('BASE_URL');
providing the value in your AppModule is done by defining a provider in your AppModule
:
providers: [ { provide: BASE_URL , useValue: "http://example.com/api" }
you can then use this InjectionToken in your LoginComponent like this:
constructor(private http: HttpClient, @Inject(BASE_URL) baseUrl: string) {
Further informations regarding injection of values can be found in the offical documentation: https://angular.io/guide/dependency-injection#dependency-injection-tokens
Upvotes: 4