2

I am very new to angular and .net core. I am writing code to do CRUD operations. I have the following code in one of my fetch project component .

import { Component } from '@angular/core';
import { ProjectDetailService } from '../services/projectdetail.service';
import { AllItProject } from '../../Models/allitproject';

@Component({
  selector: 'app-fetch-project',
  templateUrl: './fetch-project.component.html',
  styleUrls: ['./fetch-project.component.css']
})
export class FetchProjectComponent {

  public projectList: AllItProject[];

  constructor(private _projectService: ProjectDetailService) {
    this.getProjectDetails();
  }

  getProjectDetails() {
    this._projectService.getProjectDetails().subscribe(
      (data: AllItProject[]) => this.projectList = data
    );
  }

My Projectdetail.service component has the following class:

import { Injectable, Inject } from '@angular/core';
import { HttpClient, HttpInterceptor } from '@angular/common/http';
import { map } from 'rxjs/operators';
import { AllItProject } from '../../models/allitproject';


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

  myAppUrl = '';

  constructor(private _http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    this.myAppUrl = baseUrl;
  }

  getProjectDetails() {
    return this._http.get(this.myAppUrl + 'api/AllItProjectsLists/Index').pipe(map(
      response => {
        return response;
      }));
  }

when I run the project, I get a left side menu saying Fetch employee. When I click on fetch-employee,I got the error saying:

ERROR Error: Uncaught (in promise): NullInjectorError: StaticInjectorError(AppModule)[BASE_URL]: 
  StaticInjectorError(Platform: core)[BASE_URL]: 
    NullInjectorError: No provider for BASE_URL!
NullInjectorError: StaticInjectorError(AppModule)[BASE_URL]: 
  StaticInjectorError(Platform: core)[BASE_URL]: 
    NullInjectorError: No provider for BASE_URL!
    at NullInjector.get (vendor.js:39059)
    at resolveToken (vendor.js:53976)
    at tryResolveToken (vendor.js:53902)
    at StaticInjector.get (vendor.js:53752)
    at resolveToken (vendor.js:53976)
    at tryResolveToken (vendor.js:53902)
    at StaticInjector.get (vendor.js:53752)
    at resolveNgModuleDep (vendor.js:64939)
    at NgModuleRef_.get (vendor.js:66005)
    at injectInjectorOnly (vendor.js:38938)
    at resolvePromise (polyfills.js:4032)
    at resolvePromise (polyfills.js:3989)
    at polyfills.js:4093
    at ZoneDelegate.invokeTask (polyfills.js:3626)
    at Object.onInvokeTask (vendor.js:73266)
    at ZoneDelegate.invokeTask (polyfills.js:3625)
    at Zone.runTask (polyfills.js:3403)
    at drainMicroTaskQueue (polyfills.js:3794)
    at ZoneTask.invokeTask [as invoke] (polyfills.js:3704)
    at invokeTask (polyfills.js:4838)

I tried to debug my code and when I click on fetch employee menu item. I go to fetch project component constructor and then going inside getProjectDetails() in fetch-project component, I got the same error above that i mentioned above. Below is my app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { RouterModule } from '@angular/router';

import { AppComponent } from './app.component';
import { NavMenuComponent } from './nav-menu/nav-menu.component';

import { FetchProjectComponent } from './fetch-project/fetch-project.component';
import { AddProjectComponent } from './add-project/add-project.component';

@NgModule({
  declarations: [
    AppComponent,
    NavMenuComponent,
    FetchProjectComponent,
    AddProjectComponent
  ],
  imports: [
    BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
    HttpClientModule,
    FormsModule,
    ReactiveFormsModule,
    RouterModule.forRoot([

      { path: 'fetch-project', component: FetchProjectComponent },
      { path: 'register-project', component: AddProjectComponent },
      { path: 'project/edit/:id', component: AddProjectComponent },
    ])
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

below is my angular app structure:

enter image description here

I added this in my main.ts file:

export function getBaseUrl() {
  return document.getElementsByTagName('base')[0].href;
}

const providers = [
  { provide: 'BASE_URL', useFactory: getBaseUrl, deps: [] }
];

any help will be highly appreciated.

Anjali
  • 2,540
  • 7
  • 37
  • 77

3 Answers3

3

BASE_URL does not exist in your case. If you want such - create service that stores it and add to providers.

providers: [
    { provide: 'BASE_URL', useFactory: getBaseUrl }
]

Provide factory method which gets the base URL from element:

export function getBaseUrl() {
    return document.getElementsByTagName('base')[0].href;
}

And obviously you should have it in html:

<base href="/client1/" />

Nice description: http://www.projectcodify.com/angular-set-base-url-dynamically

Alex Vovchuk
  • 2,828
  • 4
  • 19
  • 40
  • I modified by main.ts file. I added the main.ts code in my original post. I am still getting the same error. Do I need to add something in my environment.ts file too. – Anjali Sep 19 '19 at 18:04
  • @Anjali And provide factory for that. I've updated answer. Just added implementation from the link above – Alex Vovchuk Sep 19 '19 at 18:09
2

The problem should be here:

  constructor(private _http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
  this.myAppUrl = baseUrl;
}

Seems you want to use a base url in your requests. The best pratice is to set that variable in the environments. Should be like this:

environment.ts

export const environment = {
production: false
BASE_URL: 'http://localhost:3000'
};

Projectdetail.service.ts

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

export class ProjectDetailService {
  myAppUrl = environment.BASE_URL;

constructor(private _http: HttpClient) { }
...
}

In this way you can set multiple BASE_URL for any kind of environment, prod, homolog, dev.. etc...

1

I think you missed to put providers in platformBrowserDynamic method. The codes below are the example of main.ts which can be used to inject 'BASE_URL'

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

export function getBaseUrl() {
    return document.getElementsByTagName('base')[0].href;
}

const providers = [
    { provide: 'BASE_URL', useFactory: getBaseUrl, deps: [] }
];

if (environment.production) {    
    enableProdMode();
}

platformBrowserDynamic(providers).bootstrapModule(AppModule)
    .catch(err => console.error(err));

And the code below is how to inject it in a constructor of component or service etc.

  constructor(@Inject('BASE_URL') baseUrl: string) {
    
  }