0

I have an angular 10 application with user section that I separated to a different library in order to make it generic and publish on github.

the user library contains the following modules: login-page,login-tab,profile-page,register-tab and shared.

the login tab module needs to get some subscription parameters for the login command.

so I defined this:

export type LoginCallback = (username: string, password: string) => Subscribable<LoginDataToken>;

now since I separated the login-page and login-tab, i need to create a different forRoot() for both of them to receive an options class that contain the loginCallback variable.

so I created this:

import {LoginCallback} from '@com-tuxin/user/src/lib/shared';

export class LoginTabOptions {

  constructor(public loginCallback: LoginCallback) {
  }

}

@Injectable()
export class LoginTabService {

  public loginCallback: LoginCallback|undefined;

  setLoginCallback(login: ((username: string, password: string) => Subscribable<LoginDataToken>) | undefined): void {
    this.loginCallback = login;
  }

}

now if i'm not correct (maybe I am), i should add forRoot() to both login-page and login-tab, since the user only requires login-page, and i need to transfer the callback to login-tab.

so this is my full login-page.module.ts:

import {ModuleWithProviders, NgModule} from '@angular/core';
import {LoginPageComponent} from '@com-tuxin/user/src/lib/login-page/login-page.component';
import {FlexModule} from '@angular/flex-layout';
import {MatTabsModule} from '@angular/material/tabs';
import {RegisterTabModule} from '@com-tuxin/user/src/lib/register-tab';
import {LoginTabModule, LoginTabOptions, LoginTabService} from '@com-tuxin/user/src/lib/login-tab';
import {RouterModule, Routes} from '@angular/router';

const routes: Routes = [  {path: 'login', component: LoginPageComponent} ];


@NgModule({
  declarations: [
    LoginPageComponent
  ],
  imports: [
    RegisterTabModule,      ### LINE BLOW IS PROBLEMATIC ###
 ###-->      LoginTabModule.forRoot({loginCallback: this.loginTabService.loginCallback}),
 ################   
 FlexModule,
    MatTabsModule,
    RouterModule.forChild(routes)

  ],
  exports: [
    LoginPageComponent
  ]
})
export class LoginPageModule {

  constructor(private loginTabService: LoginTabService) {
  }

  // tslint:disable-next-line:no-any
  static forRoot(options: LoginTabOptions): ModuleWithProviders<any> {
    return {
      ngModule: LoginPageModule,
      providers: [ {
        provide: LoginTabService,
        useFactory: () => {

          const loginTabService = new LoginTabService();
          loginTabService.setLoginCallback(options.loginCallback);
          return( loginTabService );

        }
      } ]
    };
  }

intellij returns an error that Object is possibly undefined. I would guess that in that section this it not the this of the actual class.

so first.. does my method make sense ? the user will load login-page and add a forRoot() to it and my login-age module will load login-tab and will provide to it with forRoot() the callback and it will use it.

if it's not.. what to do different ?

if it is.. how do I correct it ? the module needs to get the service with forRoot() and send it with forRoot() to the login-tab module.

1 Answer 1

1

You can try the following approach: add LoginTabModule to imports array and spread LoginTabModule providers in forRoot section:

@NgModule({
  imports: [
    LoginTabModule,  <============== tell Angular that you're going
                                     to use declarables from this module
    ...

  ],
  ...
})
export class LoginPageModule {
  static forRoot(options: LoginTabOptions): ModuleWithProviders<any> {
    return {
      ngModule: LoginPageModule,
      providers: [
        {
          provide: LoginTabService,
          useFactory: () => {
            ...
          }
        },
        ...LoginTabModule.forRoot(options).providers, <== use providers from LoginTabModule
      ]
    };
  }
}
Sign up to request clarification or add additional context in comments.

10 Comments

when adding the .providers line I get Type 'Provider[] | undefined' must have a '[Symbol.iterator]()' method that returns an iterator.
and also how in the main module i load LoginPageModule with forroot() and pasting it a function that I have in a service? how do I inject that ?
Can you please reproduce this issue here? stackblitz.com/edit/…
so I added the service my-app.service.ts stackblitz.com/edit/…
Because if you won't add it then TS will think that providers? property is 'undefined' and you can't spread undefined. Another possible solution is to use fallback like ...(LoginTabModule.forRoot(options).providers || [])
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.