Get Off My Lawn
Get Off My Lawn

Reputation: 36299

One component with two instances of the same services

I have a query builder service, and I would like to use it twice in a component. Can this be done? I have tried injecting the service twice but this doesn't seem to work, as the services just reference one another as seen here:

@Component({
  selector: 'app-manage-users',
  templateUrl: './manage-users.component.html',
  styleUrls: ['./manage-users.component.scss'],
  providers: [UserManagementQueryBuilderProvider]
})
export class ManageUsersComponent implements OnInit {

  public constructor(
    private readonly queryBuilder: QueryBuilderService,
    private readonly qb: QueryBuilderService
  ) { }

  public ngOnInit() {
    this.queryBuilder.table('users');
    console.log(this.qb['_table']); // Outputs "users"; expecting an empty string.
  }
}

I am not sure if this is because of how my provider is setup (aka, the multi option) or not but it looks like this:

export const UserManagementQueryBuilderProvider: Provider = {
  useFactory: (httpClient: HttpClient) => new QueryBuilderService(httpClient)
    .connection(environment.USER_MANAGEMENT_API),
  provide: QueryBuilderService,
  deps: [HttpClient],
  multi: false
};

If I set multi to true, I get an error saying that table is not a function.

ERROR Error: Uncaught (in promise): TypeError: this.queryBuilder.table is not a function

The QueryBuilderService then looks like this:

@Injectable({ providedIn: 'root' })
export abstract class GraphQLClientService {
  public constructor(
    private readonly httpClient: HttpClient
  ) { }
}


@Injectable()
export class QueryBuilderService extends GraphQLClientService { }

Upvotes: 0

Views: 101

Answers (1)

Rafi Henig
Rafi Henig

Reputation: 6414

Alias providers:
The useExisting provider key lets you map one token to another. In effect, the first token is an alias for the service associated with the second token, creating two ways to access the same service object. (Angular Docs)

Consider providing two InjectionTokens with UseExisting set to false, this way two different instances of QueryBuilderService will be injected, as demonstrated below:

import { Component, InjectionToken, Inject } from '@angular/core';

const QueryBuilder1 = new InjectionToken("QB1")
const QueryBuilder2 = new InjectionToken("QB2")

@Component({
  providers: [
    {
      provide: QueryBuilder1,
      useClass: QueryBuilderService,
      useExisting: false
    },
    {
      provide: QueryBuilder2,
      useClass: QueryBuilderService,
      useExisting: false
    }
  ]
})
export class ManageUsersComponent {

  public constructor(
    @Inject(QueryBuilder1) private queryBuilder1: QueryBuilderService,
    @Inject(QueryBuilder2) private queryBuilder2: QueryBuilderService
  ) { }

}

Upvotes: 3

Related Questions