-1

I have a module of dialog that has a factory defined:

@NgModule({
    declarations: [...components, ...directives],
    imports: [...modules],
    providers: [
        CustomBlockService,
        {
            provide: DocumentCustomBlock,
            useFactory: (httpClient: HttpClient, customBlockService: CustomBlockService) => {
                console.log(customBlockService.type);
                switch (customBlockService.type) {
                    case 'doc_num_date_block':
                        return new DocNumDateBlock(
                            httpClient,
                            customBlockService,
                            new DocNumDateBlockFormGroup(createFormControls(customBlockService.value)),
                        );
                    case 'find_unom_by_address_block':
                        return new FindUnomAddressBlock(
                            httpClient,
                            customBlockService,
                            new FindUnomAddressBlockFormGroup(createFormControls(customBlockService.value)),
                        );
                    default:
                        throw 'Error type custom block!';
                }
            },
            deps: [HttpClient, CustomBlockService],
        },
    ],
    entryComponents: [...components],
})
export class DialogLoadDocumentModule {}

This module of the dialog box jerks from the parent component, before the window opens, the selected block is added to the CustomBlockService service:

public setDocument(): void {
   this.customBlockService.block = this.block;
}

The first time it works, in the dialog I see the selected data this.customBlockService.block = this.block; in the DocumentCustomBlock provider.

When the window is closed and reopened with a new this.customBlockService.block = this.block; then I see old data in the service.

So, If to do the console:

useFactory: (httpClient: HttpClient, customBlockService: CustomBlockService) => {
         console.log(customBlockService.type);
});

I noted that console works only first time, then does not, despite property in CustomBlockService was chnaged.

I have tried to add this:

  { provide: CustomBlockService, useClass: CustomBlockService },

in the same module to create a new instance CustomBlockService every time when modules is loaded. But there is not success.

1 Answers1

0

The service is declared at this module's level, and module's aren't loaded multiple times. If you want to have the service class deleted, just make it a provider on the top-most component for the dialog. That way, when the component leaves the dom, the service dies with it.

P.S. make sure you clean up any subscriptions in your service via ngOnDestroy.

This StackOverflow Post has a decent answer pertaining to service lifecycles, and may be a good reference.

iamaword
  • 1,327
  • 8
  • 17
  • Could you share an example how to modify my providers or create a new? –  Sep 29 '20 at 13:17
  • So, anyway I need factory but problem is in `CustomBlockService` –  Sep 29 '20 at 13:18
  • If create a service as provider on the top of component, then should I pass it to in my factory module? –  Sep 29 '20 at 13:46
  • I have create a provider like this: `export let customBlockServiceProvider = { provide: CustomBlockService, deps: [HttpClient] };` What to do next? –  Sep 29 '20 at 13:49
  • I need this service on module level to use factory, I can not move it to components providers –  Sep 29 '20 at 13:56
  • Could you help me? –  Sep 29 '20 at 14:14
  • 1
    The Provider array is a property that can be given to modules and components alike. When you give it to a component it will cause the service to come alive when the component is created/instantiated, and die when it dies. The behavior is the same for modules, but modules don't just 'go away'. Providing provider arrays at a lower level can be useful if you want the same service in multiple modules or components to have different data, or if you want your service data to exist until the component is destroyed. – iamaword Sep 29 '20 at 17:24
  • 1
    your issue has less to do with the provider array itself (where you define a factory) and more to do with where you are defining the service (which provider array). It's also worth noting if your service has `injectable { providedIn: 'root'} at the top, then it will be effectively defined in 'app-module'. If you have this, change it to 'Injectable()' – iamaword Sep 29 '20 at 17:25
  • Can you show an example I can not get how adopt this for my case, when I need service in useFactory not in local component –  Sep 29 '20 at 17:27
  • I have tried to move my factory ptovider to component, do you mean this (where you define a factory)? –  Sep 29 '20 at 17:29
  • Problem is if I define provider in component then my parent component can not set property to service that I have in children component where I need a fabric –  Sep 29 '20 at 17:31
  • yes, if you can move the entire provider object (service/factory/etc) to a component, then it will get re-created each time the component is created (it's constructor is run). – iamaword Sep 29 '20 at 17:32
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/222258/discussion-between-alice-messis-and-iamaword). –  Sep 29 '20 at 17:33
  • If I use provider of service in child component I t should be filled in parent, how to solve this? –  Sep 29 '20 at 17:35
  • I'm a little in the dark on the component interaction structure, but I presume you would be able to pass inputs and address them in the child's ngOnInit() method. if the parent component is destroyed in between modal openings I would move it to it's provider array – iamaword Sep 29 '20 at 17:44
  • I mean another, in child component I fill service, then I open another component in dialog window, where I want to use this service in providers in factory, so where to declare the service? –  Sep 29 '20 at 17:49
  • 1
    I think I understand. You want data to be derived from a parent component, and then a child component consumes it. I would question why not just pass in input parameters to the component, but you can do something where whenever you do the logic to display the modal you do something like "myService.initialize('mydata1', foo, bar, etc...)" and do whatever you want to do to set the service data as intended. – iamaword Sep 29 '20 at 18:25
  • 1
    At that point you can have the service at the root level via injectable ... providedIn: root ... and just do specific service calls to manage the data within the service – iamaword Sep 29 '20 at 18:26