How to use a factory provider?

I need to embed a service in another service in an Angular 2 application.

After reading the documentation, I came to the conclusion that the best approach is to use the Factory Provider . However, two questions arose:

1) Documents recommend creating a HeroServiceProvider class with two "code segments":

 let heroServiceFactory = (logger: Logger, userService: UserService) => { return new HeroService(logger, userService.user.isAuthorized); }; export let heroServiceProvider = { provide: HeroService, useFactory: heroServiceFactory, deps: [Logger, UserService] }; 

My question is: what should the class look like? Where should the above code segments be added?

2) How / can I use this factory? I see this should be imported as:

 import { heroServiceProvider } from './hero.service.provider'; @Component({ selector: 'my-selector', template: ' ', providers: [heroServiceProvider] }) 

How then can you get and access the desired parameterized service?

+10
source share
5 answers

I encountered the same problems as in app_initalizer, after a long search I found a solution below. Perhaps this will help your scenario.

 @NgModule({ imports: [ BrowserModule], ... providers: [ { provide: HeroService, useFactory: heroServiceFactory, deps: [Logger, UserService], multi: true } ] }) export class AppModule {} export function heroServiceFactory = (logger: Logger, userService: UserService) => { return new HeroService(logger, userService.user.isAuthorized); }; 
+16
source

I don’t have enough points to comment on @mgmg answer, but there is some useful information here ...

I used the provider factory template specified in the documentation (and the subject of this question) in my own application, but continued to receive a compilation error

ERROR in error detected during static resolution of character values. Feature calls are not supported. Try replacing a function or lambda with a link to the exported function ...

In fact, when a factory dependency is used in the root module, all of its dependencies must be provided with it.

This means that the code block specified in @mgmg answer must have strictly dependent services.

 import { heroServiceProvider } from './hero.service.provider'; import { UserService } from './user.service'; import { Logger } from './logger.service'; ... @NgModule({ ... providers: [ Logger, UserService, heroServiceProvider // Wrapper for: //{ provide: HeroService, // useFactory: (logger: Logger, userService: UserService) => { // return new HeroService(logger, userService.user.isAuthorized) // }, // deps: [Logger, UserService] //}; ], bootstrap: [ AppComponent ] }) 

Please note that in corner documents here heroServiceProvider is provided on heroes.component , and not in app.module , and links to Logger and UserService are not needed here. I believe that these two dependencies come from a higher level of the injector tree.

+2
source

1) The first part of your question is simple: you just keep the snippet provided in a separate file and import it into the component, as shown in your question:

import { heroServiceProvider } from './hero.service.provider';

2) As for the actual use, you really don't need to change the service code in the component. Just keep using it if the original service has been introduced. You do not even need to change the component constructor. The idea of ​​a service provider is that you can customize your service based on each component using a specialized service provider for each component, and you will perform component-specific initialization in the factory function. Just remember to list the service provider in the decorator of your component, Angular takes care of the rest "automatically."

+1
source

Question 1:
What should the whole class look like? Where should the above code segments be added?

Answer:
You can create a file containing the code for the hero service provider and its factory function. This file may be called hero.service.provider.ts .
And write the hero service code in another file called hero.service.ts .

Check out this article on how to use Angular service providers to see more examples.

File hero.service.provider.ts :

 import { HeroService } from './hero.service'; import { Logger } from './logger.service'; import { UserService } from './user.service'; let heroServiceFactory = (logger: Logger, userService: UserService) => { return new HeroService(logger, userService.user.isAuthorized); }; export let heroServiceProvider = { provide: HeroService, useFactory: heroServiceFactory, deps: [Logger, UserService] }; 

Question 2: How / can I use this factory?

Answer:
According to the sample code you provided, the factory can be configured for the service using the provider field in the @Component decorator, and the service can be implemented through the class constructor or using the angular injection object.

However, shaking the tree does not work when the factory provider configured this path. Check out this example angular tree swing service if you need the tree to work.

 import { heroServiceProvider } from './hero.service.provider'; import { HeroService } from './hero.service'; @Component({ selector: 'my-selector', template: '', providers: [heroServiceProvider] }) export class HeroComponent { constructor(private heroService: HeroService) { } } 
+1
source

Today I came across the same question and found some solution.

1) I found the exact code in angular.io, see below: https://github.com/angular/angular.io/blob/master/public/docs/_examples/dependency-injection/ts/src/app/heroes /hero.service.provider.ts (link updated March 15, 2017).
From this code, heroServiceProvider does not need to be a class.

2) In app.module.ts there is a providers property in @NgModule. And you can add heroServiceProvider to this as below:

 import { heroServiceProvider } from './hero.service.provider'; ... @NgModule({ ... providers: [ heroServiceProvider ], bootstrap: [ AppComponent ] }) 

By providing the service at @NgModule, you can use this service in the application area.

0
source

Source: https://habr.com/ru/post/1257567/


All Articles