0
votes

I have created a component base in TypeScript which I would like to share many services.

export abstract class ComponentBase<T> {
  constructor(protected http:Http, protected router: Router, protected route: ActivatedRoute, protected params: Params) {
  }
}

The problem is that I have multiple nested types and so whenever I have to derive any level down the hierarchy. Each derived type would look something like this passing down the base's injected parameters.

import { Http } from '@angular/http';
import { Router, ActivatedRoute, Params } from '@angular/router';
export  class SomeDerivedType extends ComponentBase<SomeType> {
  constructor(protected http: Http, protected router: Router, protected route: ActivatedRoute, protected params: Params) {
    super(http, router, route, params);
  }
}

I have to chain my constructors to satisfy the base class's constructor parameters. This is quite annoying overhead. Therefore, I have created a Services class to hold all the encapsulated dependencies.

import { Injectable } from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';
import { Http } from "@angular/http";

@Injectable()
export class Services {
  constructor(public http:Http, public router: Router,  public route: ActivatedRoute, public params: Params) {
  }
}

I thought I should be able to just inject this services class into the components as follows.

import { Services } from './services'
export class SomeDerivedType extends ComponentBase<any> {
  constructor(protected services: Services) {
    super(services);
  }
}

And the component base now looks as follows:

import { Services } from './services';
import { Http } from '@angular/http';
import { Router, ActivatedRoute, Params } from '@angular/router';

export abstract class ComponentBase<T> {
  http: Http;
  router: Router;
  route: ActivatedRoute;
  params: Params;
  constructor(protected services: Services ) {
    this.http = services.http;
    this.route = services.route;
    this.router = services.router;
    this.params = services.params;
  }
}

This unfortunately is not working for me, instead I get the following error:

(index):63 Error: Error: Can't resolve all parameters for Services: ([object Object], [object Object], [object Object], ?).

So, naturally my question is, "Is there a way to have the dependent services (ie. http,router,route, and params services) injected into my services class?"

1
your component base and any derived classes need to be decorated with the injectable decorator (or directive or component) if they have injected dependencies, but as an aside, you shouldn't be structuring your app this way. It will be nearly impossible to maintain with all the hidden dependencies you're creating.bryan60
I am not sure what I would have to maintain can you elaborate? Also, I am not injecting anything other than the service class so why would I need to decorate component classes with @injectable?jwize
any advantage of doing this way??Aravind
Just less imports and code to manage. The imports can go away and the constructor looks simple in all places.jwize
If you're injecting anything via angulars dependency injection system, which you are, you need to decorate with the injectable decorator. This is how angular knows to register it with the injector. Your code has hidden interwoven dependencies. You should be asking yourself why you have so many components that need all these services. The error you're seeing is usually thrown in the case of a circular dependency, which implies you've already created a hidden accidental circular dependency by trying to save yourself a few characters in your constructor. Good Angular is declarative, this is not.bryan60

1 Answers

1
votes

Well, as it turns out I just missed something about angular that wasn't clear to me. I have only been using it for a little while. The problem was actually simple. Params is not a service.

(index):63 Error: Error: Can't resolve all parameters for Services: ([object Object], [object Object], [object Object], ?).

The message threw me off because it said can't resolve all. I misinterpreted it, as it was really telling me that one of the parameters was not being resolved. In my case protected params : Params.

This code now works beautifully just as I hoped it would by removing the params item.