Angular 9 : Error NG2003: No suitable injection token for parameter 'url' of class 'DataService'. Found string

Frontier picture Frontier · Mar 22, 2020 · Viewed 12.6k times · Source

While working on a program that I am facing an issue with, constructor and its dependency injection from its child class.

  • DataService: A service class which has all the CRUD operation at one place and also has a parameterized constructor for injecting the end-point URL and HTTP from its child classes.
constructor(private url: string, private http: Http) { }
  • PostService : A service class which extends the above DataService class to have the CRUD operation functionality within it and a one-parameterized constructor and internally calls the super(endPointURL, httpObject) as below :
constructor(http: Http) {
    super('https://jsonplaceholder.typicode.com/posts', http);
}

Before this re-factoring (moving all the common CRUD operation and extending it by child classes) my code was working as expected but AFTER the above changes I am getting the below error:

Date: 2020-03-22T15:26:23.248Z - Hash: 7130497a38c152c58258
5 unchanged chunks

Time: 1859ms

ERROR in src/app/services/data.service.ts:14:23 - error NG2003: No suitable injection token for parameter 'url' of class 'DataService'.
Found string

14   constructor(private url: string, private http: Http) { }

Also, when I remove the url param from Datsource constructor (modify PostService.ts accordingly) the api is working as expected. Not sure why !!!

I am using:

Angular CLI: 9.0.4 Node: 12.16.1 OS: win32 x64

Angular: ... Ivy Workspace:

Package Version

@angular-devkit/architect 0.900.4

@angular-devkit/core 9.0.4

@angular-devkit/schematics 9.0.4

@schematics/angular 9.0.4

@schematics/update 0.900.4

rxjs 6.5.3

DataService.ts

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { AppError } from '../common/app-error';
import { NotFoundError } from '../common/not-found-error';
import { BadInput } from '../common/bad-input';

@Injectable()
export class DataService {

//   private url = 'https://jsonplaceholder.typicode.com/posts';

  constructor(private url: string, private http: Http) { }

  getAll() {
    return this.http.get(this.url).pipe(catchError(this.errorHandle));
  } 

  create(resource) {
    return this.http.post(this.url, JSON.stringify(resource))
      .pipe(catchError(this.errorHandle));
  }

  update(resource) {
    return this.http.patch(this.url + '/' + resource.id, JSON.stringify({ isRead: true }))
    .pipe(catchError(this.errorHandle));
  }

  delete(resource) {
    return this.http.delete(this.url + '/' + resource.id)
      .pipe(catchError(this.errorHandle));
  }
  
  private errorHandle(error: Response){
    if (error.status === 404) {
      return throwError(new NotFoundError());
    }
    if (error.status === 400) {
      return throwError(new BadInput(error.json()));
    }
    return throwError(new AppError(error));
  }

}

PostService.ts

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { DataService } from './data.service';

@Injectable()
export class PostService extends DataService {

  constructor(http: Http) {
    super('https://jsonplaceholder.typicode.com/posts', http);
  }

}

Answer

Useme Alehosaini picture Useme Alehosaini · Mar 25, 2020

In DataService.ts :

Update the Constructor.

//import { Inject } from '@angular/core';

constructor(@Inject(String) private url: string, private http: Http)

UPDATED (Explanation):

According to https://angular-2-training-book.rangle.io/di/angular2/inject_and_injectable ;

@Inject() is a manual mechanism for letting Angular know that a parameter must be injected.

@Inject decorator is only needed for injecting primitives.

The primitive types are number, string, boolean, bigint, symbol, null, undefined.

The other (alternative) way can be used is:

//import { Inject } from '@angular/core';

@Inject('url') private url: string;