Hafnernuss
Hafnernuss

Reputation: 2827

Preventing recursive import of angular modules

I have refactored my angular app with a quite monolithic shared feature module to several smaller ones. I tried to follow this approach here because I agree with the reasoning.

However, I ran into a problem with what seems to be a cyclic dependency. Basically I have a triggerA that dynamically spawns modalA which in turn contains a triggerB that will spawn modalB which has a triggerA. This works fine as long as all components are in one module, but as soon as I split them (each component in it's own module), a cyclic dependency occurrs, because triggerA imports modalA which imports triggerB which imports modalB which then again imports triggerA.

I know, this seems like bad design, and it could very well be the case, however, here is the real world use-case:

Suppose I have a modal for showing informations regarding a specific event. This event has participants, and I want to have the possibility of viewing the profile of a participant from within that modal. However, this modal also contains a list of all events in which this person participates, which in turn... you get the picture. This seemed quite elegant because I could reuse all components to stay DRY. Leaving all those components in one module does not feel right, because I would eventually mix a lot of things together that don't belong together necessarily.

I have created a mre here.

This works! But as soon as I remove the comments from line 12 in trigger-a.module.ts, there is a recursive dependency. But I have to keep the import of the module, otherwhise I'll get a lot of schema errors.

I therefore have a few questions:

What would be the recommended approach here? On one hand it seems to work if I simply do not list the module unter imports, however, this seems very hacky to me. The second option kind of... defeats the purpose of having many small modules since I have to import at least those with a "cross-dependency" in the apps module directly.

This somehow feels very off, and I get the suspicion that I'm doing something that shouldn't be done. However, I think my use-case is valid. I would be grateful for any suggestions you might have.

Upvotes: 1

Views: 691

Answers (1)

Andres2142
Andres2142

Reputation: 2897

I managed to solve it by deleting both trigger modules, and I have created a new module called TriggersModule like this:

import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { NgbModalModule } from '@ng-bootstrap/ng-bootstrap';
import { TriggerAComponent } from './trigger-a/trigger-a/trigger-a.component';
import { TriggerBComponent } from './trigger-b/trigger-b/trigger-b.component';

@NgModule({
  declarations: [TriggerAComponent, TriggerBComponent],
  imports: [CommonModule, NgbModalModule],
  exports: [TriggerAComponent, TriggerBComponent],
})
export class TriggersModule {}

Modal A:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ModalAComponent } from './modal-a/modal-a.component';
import { NgbModalModule } from '@ng-bootstrap/ng-bootstrap';
import { TriggersModule } from '../triggers.module';

@NgModule({
  declarations: [ModalAComponent],
  imports: [CommonModule, NgbModalModule, TriggersModule],
  exports: [ModalAComponent],
})
export class ModalAModule {}

Modal B:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ModalBComponent } from './modal-b/modal-b.component';
import { TriggersModule } from '../triggers.module';

@NgModule({
  declarations: [ModalBComponent],
  imports: [CommonModule, TriggersModule],
  exports: [ModalBComponent],
})
export class ModalBModule {}

App module:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { TriggersModule } from './triggers.module';
import { ModalAModule } from './modal-a/modal-a.module';
import { ModalBModule } from './modal-b/modal-b.module';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    NgbModule,
    ModalAModule,
    ModalBModule,
    TriggersModule,
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

Upvotes: 1

Related Questions