title: Angular circular dependency warning
body: <p>tl;dr: scroll down to solution</p>
  
  <p>I have a circular dependency and I am getting a warning, rightfully so, however, I am managing it. The issue is that I have a chat component. In the corner you can select to see their profile page, while in their profile page you have the option to send them a message, hence the circular dependency. I am managing this by</p>
  
  <h3>chat.component</h3>
  
  <pre class="lang-js prettyprint-override"><code>public async openProfile(): Promise&lt;void&gt; {
    this.modalCtrl.dismiss(); //closing the chat component before opening the profile modal
    const profile = await this.modalCtrl.create({
      component: ProfileComponent,
    });
    await profile.present();
  } 
  </code></pre>
  
  <h3>profile.component</h3>
  
  <pre class="lang-js prettyprint-override"><code>public async openChat(): Promise&lt;void&gt; {
    this.modalCtrl.dismiss(); //closing the profile component before opening the chat modal
    const chat = await this.modalCtrl.create({
      component: ProfileComponent,
    });
    await chat.present();
  } 
  </code></pre>
  
  <p>Is there an easier way of handling this circular dependency?</p>
  
  <p>UPDATE:
  as per the suggestion below I tried creating a service. However now I have a three way dependency circle:</p>
  
  <h3>chat.component</h3>
  
  <pre class="lang-js prettyprint-override"><code>private modalService: ModalService;
  
  constructor(modalService: ModalService){
    this.modalService = modalService
  }
  
  public async openProfile(): Promise&lt;void&gt; {
    this.modalService.openProfile(this.userData);
  } 
  </code></pre>
  
  <h3>profile.component</h3>
  
  <pre class="lang-js prettyprint-override"><code>private modalService: ModalService;
  
  constructor(modalService: ModalService){
    this.modalService = modalService
  }
  
  public async openChat(): Promise&lt;void&gt; {
    this.modalService.openChat(this.userData);
  }
  </code></pre>
  
  <h3>modal.service</h3>
  
  <pre class="lang-js prettyprint-override"><code>import { ModalController } from '@ionic/angular';
  import { Injectable } from '@angular/core';
  import { ProfileComponent } from '../../components/profile/profile.component';
  import { ChatComponent } from '../../components/chat/chat.component';
  import { UserData } from '../../interfaces/UserData/userData.interface';
  
  @Injectable({
    providedIn: 'root',
  })
  export class ModalService {
    private modal: ModalController;
    public constructor(modal: ModalController) {
      this.modal = modal;
    }
  
    public async openProfileComponent(user: UserData): Promise&lt;void&gt; {
      this.modal.dismiss();
      const profile = await this.modal.create({
        component: ProfileComponent,
        componentProps: {
          contact: user,
        },
      });
  
      await profile.present();
    }
  
    public async openChatComponent(user: UserData): Promise&lt;void&gt; {
      this.modal.dismiss();
      const chat = await this.modal.create({
        component: ChatComponent,
        componentProps: {
          contact: user,
        },
      });
  
      await chat.present();
    }
  
    public close(): void {
      this.modal.dismiss();
    }
  }
  
  </code></pre>
  
  <p><em>UPDATE</em> Stackblitz is too unstable with Ionic 4 so I can't replicate on it so here is a <a href="https://gist.github.com/ctfrancia/5ce346b3ee228eb1d75b3306f701c71d" rel="nofollow noreferrer">gist</a> with the information and related code.</p>
  
  <p><em>UPDATE2</em>
  I took the advice mentioned in answers but still getting the error. In order to do that, I created a <code>shared.module.ts</code> that looks like this:</p>
  
  <pre class="lang-js prettyprint-override"><code>import { UserService } from './componentServices/user/user.service';
  import { ModalService } from './componentServices/modal/modal.service';
  import { AuthenticationSecurityService } from './componentServices/auth_security/authentication-security.service';
  import { AuthGuardService } from '../_guards/auth-guard.service';
  import { ApiService } from './componentServices/api/api.service';
  import { ChatService } from './components/chat/socketIO/chat.service';
  
  @NgModule({
    imports: [CommonModule, ReactiveFormsModule, IonicModule.forRoot(), FormsModule, IonicModule],
    declarations: [
      // various components
    ],
    exports: [
      // various components and common modules
    ],
  })
  export class SharedModule {
    static forRoot(): ModuleWithProviders {
      return {
        ngModule: SharedModule,
        providers: [
          UserService,
          ModalService,
          DashboardService,
          AuthenticationSecurityService,
          AuthGuardService,
          ApiService,
          ChatService,
        ],
      };
    }
  }
  </code></pre>
  
  <h2>app.module.ts</h2>
  
  <pre><code>imports: [
      SharedModule.forRoot(),
  ]
  </code></pre>
  
  <pre><code>client:135 Circular dependency detected:
  src/sharedModules/componentServices/modal/modal.service.ts -&gt; src/sharedModules/components/profile/profile.component.ts -&gt; src/sharedModules/componentServices/modal/modal.service.ts
  
  client:135 Circular dependency detected:
  src/sharedModules/components/chat/chat.component.ts -&gt; src/sharedModules/components/search/search.component.ts -&gt; src/sharedModules/components/profile/profile.component.ts -&gt; src/sharedModules/componentServices/modal/modal.service.ts -&gt; src/sharedModules/components/chat/chat.component.ts
  
  client:135 Circular dependency detected:
  src/sharedModules/components/profile/profile.component.ts -&gt; src/sharedModules/componentServices/modal/modal.service.ts -&gt; src/sharedModules/components/profile/profile.component.ts
  
  client:135 Circular dependency detected:
  src/sharedModules/components/search/search.component.ts -&gt; src/sharedModules/components/profile/profile.component.ts -&gt; src/sharedModules/componentServices/modal/modal.service.ts -&gt; src/sharedModules/components/chat/chat.component.ts -&gt; src/sharedModules/components/search/search.component.ts
  </code></pre>
  
  <h1>SOLUTION</h1>
  
  <p>as @bryan60 and @Luis said there has to be a buffer, so what I did was follow the emitting route that they both had suggested. Bryan gives more code look like, where Luis gives a great responsibility summary. here is how I refactored it:</p>
  
  <h2>app.component.ts</h2>
  
  <pre class="lang-js prettyprint-override"><code>  public initializeApp(): void {
      this.platform.ready().then((): void =&gt; {
        this.statusBar.styleDefault();
        this.splashScreen.hide();
        this._subToObservables();
      });
    }
  
    private _subToObservables(): void {
      this.modalService.openModal$.subscribe(
        async (e: ModalEmitInterface): Promise&lt;void&gt; =&gt; {
          const { command, data } = e;
          switch (command) {
            case 'open-profile':
              const profile = await this.modalCtrl.create({
                component: ProfileComponent,
                componentProps: {
                  contact: data,
                },
              });
              await profile.present();
              break;
  
            case 'open-chat':
              // same as above
              break;
  
            default:
              break;
          }
        },
      );
    }
  </code></pre>
  
  <h2>modalSignal.service.ts</h2>
  
  <pre class="lang-js prettyprint-override"><code>export class ModalService {
    private openModalSubject: Subject&lt;ModalEmitInterface&gt; = new Subject&lt;ModalEmitInterface&gt;();
    public readonly openModal$: Observable&lt;ModalEmitInterface&gt; = this.openModalSubject.asObservable();
  
    private emitPayload: ModalEmitInterface;
    public openProfileComponent(user: UserData): void {
      this.emitPayload = {
        command: 'open-profile',
        data: user,
      };
      this.openModalSubject.next(this.emitPayload);
    }
  
    // repeat for others
  }
  </code></pre>
  
  <h2>chat.component.html</h2>
  
  <pre class="lang-html prettyprint-override"><code>&lt;button (click)="openProfile(user)"&gt;click me&lt;/button&gt;
  </code></pre>
  
  <p>chat.component.ts</p>
  
  <pre class="lang-js prettyprint-override"><code>export class ChatComponent {
    public constructor(private modalSignal: ModalService){}
  
    private openProfile(user: UserData): void {
      this.modalSignal.openProfileComponent(user);
    }
  }
  
  </code></pre>
  
  <p>thats it, although you still need to make sure that you are closing the modals or they will continue to stack.</p>