qkhanhpro
qkhanhpro

Reputation: 5240

Correct use of Angular TypeScript constructor - Can't resolve all parameters for

@Injectable({
  providedIn: 'root',
  /* useFactory: () => new MyService(MyAnotherService.myInteger) */
})
export class MyService{

  constructor(private someInteger?: number) {
    // doThings with someInteger
  }

--aot build will complain that Warning: Can't resolve all parameters for...

In fact, due to the useFactory: () part, we are still able to run our application correctly. But I do not know if this is the right way or not

We can, of course, change the constructor to

constructor(private anotherService?: MyAnotherService) {
        // doThings with anotherService
      }

To shut the build warning, However I do not think that MyService should be dependent on MyAnotherService when It can be just dependent on a primitive, It's also bad for code reusability

What is the best thing to do in this situation?

My idea is that. Angular use Decorator to instruct that it is an Angular component ( am I right? ) So the main logic body should not always be coupled to Angular DI logic, especially if It is a service. We can pull the service code and plug it elsewhere ( Using DI or not )

Upvotes: 2

Views: 3406

Answers (5)

David
David

Reputation: 34475

You can use an optional injection token

token.ts

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

export const INTEGER_TOKEN= new InjectionToken<number>('IntegerToken');

app.module.ts

import {INTEGER_TOKEN} from './token';

@NgModule({
//...
  ],
  providers: [
    {
      provide: INTEGER_TOKEN,
      useValue: 1 //Or factory if you need one
    },

service.ts

import {INTEGER_TOKEN} from './token';

import {Injectable, Inject, Optional} from '@angular/core';


@Injectable({
  providedIn: 'root',

})
export class MyService{

  constructor(@Optional() @Inject(INTEGER_TOKEN) private someInteger?: number) {
    // doThings with someInteger
  }

Upvotes: 2

DEVolkan
DEVolkan

Reputation: 592

The common practice is to put so little logic in it as possible. Most of the time the constructor is used to inject dependencies.

constructor(private anotherService: AnotherService) {
    // **don't** do Things with anotherService
  }

and then use it in another functions

ngOnInit() {
   this.anotherService.getValue().subscribe((value) => {
      // do something
   });
}

The function ngOnInit() will be called when the DOM from the component was created, all dependencies was injected and all inputs was binded. It's common practice to use the ngOnInit() even if the logic doesn't depend on DOM, input binding or Dependencie injection.

Upvotes: 2

kctang
kctang

Reputation: 11202

Consider these:

  1. When facing issues that works in dev's ng serve but not in AOT, turn on "strictMetadataEmit" : true to get details on what's wrong.
  2. For example, AOT does not work with arrow functions.
  3. Use @Optional() for optional dependencies.

Upvotes: 1

Chanaka Weerasinghe
Chanaka Weerasinghe

Reputation: 5742

Constructor should generally be used just for Dependency Injection

 <my-component [state]="'joining'"></my-component>

    export class MyService{
  state: string;
      constructor() { 
        console.log(this.state) // => undefined
      }
      ngOnInit() {
        console.log(this.state) // => 'joining'
      }
    }

Upvotes: 0

user10292634
user10292634

Reputation:

just remove the '?'

import {MyAnotherService} from '/pathto your service';
     constructor(private anotherService: MyAnotherService) {
           //prodedures
          }

or for the params:

myVariable: any;
constructor(private anotherService: MyAnotherService) {

this.myVariable = [];
}

Upvotes: 0

Related Questions