[FIXED] How to show dynamic component in Angular Ionic Modal

Issue

In an Angular Ionic app I want to show a modal presenting content from a dynamic loaded component.

I’m using ion-modal tag, but since it uses ng-template tag to present content, I’m not able to access the host container inside it:

This is a Stackblitz demo showing the non working code.

Here you can see my host div inside the ng-template:

  <ion-modal [trigger]="'open-modal-2'">
    <ion-content [scrollY]="false">
      <ng-template>
        <div #myHost></div> <!-- host inside ng-template! -->
      </ng-template>
    </ion-content>
  </ion-modal>

When I try to access myHost, it is undefined (even using AfterViewInit):

export class AppComponent implements AfterViewInit {
 @ViewChild('myHost', { static: false, read: ViewContainerRef }) myHost;

  ngAfterViewInit(): void {
    console.log(this.myHost); // undefined
    const componentRef = this.myHost.createComponent(HelloComponent);
  }
}

Solution

I arrived to the conclusion that for this case it’s necessary to use Ionic ModalController instead of ion-modal. See Controller Modals.

This is the working Stackblitz demo.

app.component.ts Inject ModalController service and create method for presenting the modal:

...
export class AppComponent {
  name: string = '';

  constructor(private modalCtrl: ModalController) {}

  async openModal() {
    const modal = await this.modalCtrl.create({
      component: CustomComponent,
    });
    modal.present();

    const { data, role } = await modal.onWillDismiss();

    if (role === 'confirm') {
      this.name = data;
    }
  }
}

app.component.html Assign click event to the method:

<ion-app>
  <ion-content>
    <ion-list>
      <ion-item [button]="true" (click)="openModal()">
        <ion-label>ControllerModal Modal</ion-label>
      </ion-item>
    </ion-list>
    <h1>Hello {{ name }}</h1>
  </ion-content>
</ion-app>

custom.component.ts Create the component that will be inserted in the modal; it also injects ModalController so it can dismiss:

...
export class CustomComponent implements OnInit {
  name: string;

  constructor(private modalCtrl: ModalController) {}

  ngOnInit() {}

  cancel() {
    this.modalCtrl.dismiss(null, 'cancel');
  }

  confirm() {
    this.modalCtrl.dismiss(this.name, 'confirm');
  }
}

custom.component.html Just a simple form with two buttons:

<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-button color="medium" (click)="cancel()">Cancel</ion-button>
    </ion-buttons>
    <ion-title>Welcome</ion-title>
    <ion-buttons slot="end">
      <ion-button (click)="confirm()">Confirm</ion-button>
    </ion-buttons>
  </ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
  <ion-item>
    <ion-label position="stacked">Your name</ion-label>
    <ion-input [(ngModel)]="name" placeholder="Your name"></ion-input>
  </ion-item>
</ion-content>

Answered By – Gustavo

Answer Checked By – Gilberto Lyons (Easybugfix Admin)

Leave a Reply

(*) Required, Your email will not be published