NgModuleFactoryLoader.load() 找不到模块

NgModuleFactoryLoader.load() is not able to find the module

Please refer my project structure here 我创建了一个包含多个延迟加载嵌套模块的项目。

  1. 在应用程序启动时加载 AppModule
  2. 当用户点击登录按钮时 LoginModule 被加载
  3. 如果用户存在,即如果登录成功 IntegratedPmntsModule,它是 AppModule 的另一个功能模块,应该从 login-routing.module.ts 延迟加载。它使用“button routerLink='integratePayments' class="pmntButton"' 完美加载 IntegratedPmntsModule,但这不是我想要的。

我的要求是有条件地加载功能子模块,如组件 login.component.ts 所示,当用户登录失败时,他应该被导航到登录(它工作正常,因为 LoginModule 已经被延迟加载)当登录成功时,用户应该被导航到 IntegratedPmntsModule 中存在的 IntegratedPaymentsComponent(这并没有发生)。

  1. this.router.navigate(['integratedPayments']); -- 给出'未捕获(承诺):错误:无法匹配任何路由 'integratedPayments'

  2. 我什至尝试使用 NgModuleFactoryLoader.load() 的 load() 方法加载 IntegratedPmntsModule,它给出 'module is not found error'

login.component.ts

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {

  loginFormGroup: FormGroup;
  customerModel:CustomerLoginModel = new CustomerLoginModel();
  userExist: Boolean = true;

  constructor(private loginService: LoginService, private router: Router, private readonly loader: NgModuleFactoryLoader) { }

  ngOnInit(): void {
    this.loginFormGroup = new FormGroup({
      customerId: new FormControl('', [Validators.required,Validators.maxLength(20),Validators.pattern('^[a-zA-Z0-9]+([._]?[a-zA-Z0-9]+)*$')]),
      password: new FormControl('', [Validators.required, Validators.maxLength(15)])
    })
  }
  submitLoginForm(formGroup: FormGroup): any{
   
   this.customerModel.setCustomerId(formGroup.value.customerId);
   this.customerModel.setPassword(formGroup.value.password);
   this.loginService.authenticateCustomer(this.customerModel).subscribe(
     response=>{
       this.userExist=response},
      error=>{
        console.log(error)
      }
    );
      if(this.userExist){
          //this.loader.load('./app/integrate-pmnts-module/integrate-pmnts.module#IntegratePmntsModule').
          //then(factory =>this.router.navigate(['integratedPayments']));
          this.router.navigate(['integratedPayments']);
      }
      else
        this.router.navigate(['login']);
  }

}

app-routing.module.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LoginauthGuard } from './login/loginauth.guard';


const routes: Routes = [
 
  {
    path: 'login',
    loadChildren: () => import('./login/login.module').then(mdule=>mdule.LoginModule),
  },
  
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

login-routing.module.ts


const routes: Routes = [
  {
    path: '',
    component: LoginComponent,
    //canDeactivate: [LoginauthGuard]
  },
  {
    path: 'integratedPayments',
    loadChildren: () => import('../integrate-pmnts-module/integrate-pmnts.module').then(mdule=>mdule.IntegratePmntsModule)
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class LoginRoutingModule { 

}

login.component.html


<html>
    <form [formGroup]="loginFormGroup" (ngSubmit)="submitLoginForm(loginFormGroup)"> 
            Customer Id:<input type="text" formControlName="customerId" placeholder="Enter Customer ID"><br><br>
            Password: <input type="password" formControlName="password" placeholder="Enter Password"><br><br>
            <div *ngIf='!userExist'>
                Please enter valid credentials!
            </div><br><br>
        <button class="pmntButton">Login</button>
    </form>
</html>

integratepayments-routing.module.ts


const routes: Routes = [
    {
        path: '',
        component: IntegratedPaymentsComponent
    },
    {
      path: 'eftPaymentsPage',
      loadChildren: () => import('src/app/integrate-pmnts-module/eft-payments-module/eft-payments-module').then(mod=>mod.EftPaymentsModuleModule)
    }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class IntegratedPaymentsRoutingModule { }

因为 integratedPayments 路由是 login 路由的 child,你应该使用:this.router.navigateByUrl('login/integratedPayments').

这可能仍然不起作用,因为来自 login-routing.module.ts 的路由定义如下:

const routes: Routes = [
  {
    path: '',
    component: LoginComponent,
    //canDeactivate: [LoginauthGuard]
  },
  {
    path: 'integratedPayments',
    loadChildren: () => import('../integrate-pmnts-module/integrate-pmnts.module').then(mdule=>mdule.IntegratePmntsModule)
  }
];

这意味着第一条路线 (path: '') 将 始终匹配 。为了避免这种情况,您可以做的是添加 pathMatch: 'full' 选项:

const routes: Routes = [
  {
    path: '',
    component: LoginComponent,
    pathMatch: 'full'
  },
  {
    path: 'integratedPayments',
    loadChildren: () => import('../integrate-pmnts-module/integrate-pmnts.module').then(mdule=>mdule.IntegratePmntsModule)
  }
];

perfectly with 'button routerLink='integratePayments' class="pmntButton"'

这是因为 RouterLink 指令在内部的工作方式。

让我们看看 what happens 当您单击具有此指令的按钮时:

@HostListener('click')
  onClick(): boolean {
    const extras = {
      skipLocationChange: attrBoolValue(this.skipLocationChange),
      replaceUrl: attrBoolValue(this.replaceUrl),
      state: this.state,
    };
    this.router.navigateByUrl(this.urlTree, extras);
    return true;
  }

  get urlTree(): UrlTree {
    return this.router.createUrlTree(this.commands, {
      relativeTo: this.route, // !
      queryParams: this.queryParams,
      fragment: this.fragment,
      preserveQueryParams: attrBoolValue(this.preserve),
      queryParamsHandling: this.queryParamsHandling,
      preserveFragment: attrBoolValue(this.preserveFragment),
    });
  }

如您所见,它使用了 relativeTo 选项。 this.route 被注入为 private route: ActivatedRoute.

这意味着您可以通过登录组件使其与 this.router.navigate(['integratedPayments']); 一起工作。

您必须先在登录组件中注入 ActivatedRoute,然后将 relativeTo 选项添加到 route.navigate:

this.router.navigate(['integratedPayments'], { relativeTo: this.route });