Creating an Angular material modal that uses a component wrapper and takes a component as a parameter

Currently, I am in the process of developing a dialog service that will showcase a wrapper component whose parameter is a component to be displayed as the content of the wrapper.

open(component: any | TemplateRef<any>, params, viewMode: ViewMode = ViewMode.EDIT, className: string[] = ['as-dialog', 'as-dialog-large']): Observable<any> {

// Need to find a way to nest the component in AsDialogWrapperComponent
// and then display AsDialogWrapperComponent with the nested component as its content
    this.dialogRef = this.matDialog.open(AsDialogWrapperComponent, {
      data: {
        params,
        viewMode
      },
      panelClass: className
    });
    return this.dialogRef.afterClosed();
  }

The code for the wrapper would look like this:

<div class="as-box as-vertical as-fh">
  <div class="as-dialog-header">
    <p class="as-dialog-header-text" mat-dialog-title #title></p>
  </div>
  <mat-dialog-content #content></mat-dialog-content>
</div>

I am interested in finding a way to nest the component provided as a parameter. I have attempted using the componentFactoryResolver, but was unable to resolve it in the end.

This functionality is necessary because some views can be both modals and full-screen views. Therefore, a modal wrapper that accepts a title as a parameter and modal actions either as parameters or within a custom button bar could be utilized.

Any advice or tips on how to achieve this nesting would be greatly appreciated. Thank you.

Answer №1

Consider fetching data for your component from a service instead of passing it through the MAT_DIALOG_DATA injection token. This way, you can use your component as either a full-screen view or a dialog without requiring a wrapper. Remember to include it in the entryComponents list of your module.

Alternatively, here's a possible solution to your query within your wrapper dialog "AsDialogWrapperComponent":

  private createComponent(config: DialogConfig) {
    this.destroyComponent();
    const factory: Component<DialogBase<any>> = this.resolver.resolveComponentFactory(config.component);
    this.componentRef = this.container.createComponent(factory);
    (this.componentRef.instance as DialogBase<any>).data = config.data;
    (this.componentRef.instance as DialogBase<any>).close
      .pipe(take(1))
      .subscribe(this.closeDialog.bind(this));
    this.cdRef.detectChanges();
  }

  private destroyComponent() {
    this.container.clear();
    if (this.componentRef) {
      this.componentRef.destroy();
      this.componentRef = null;
    }
  }

Injecting 'config' in the wrapper dialog:

constructor(@Inject(MAT_DIALOG_DATA) public data: DialogConfig) {}

The structure of 'config':

export interface DialogConfig {
  component: { new(...args: any[]): any; };
  data: any;
}

'DialogBase' can be a superclass that your inner component extends:

import {
  EventEmitter,
  Output
} from '@angular/core';

export class DialogBase<T> {

  @Output() close: EventEmitter<void> = new EventEmitter();

  private _data: T;

  constructor() {
  }

  set data(data: T) {
    this._data = data;
  }

  get data(): T {
    return this._data;
  }
}

'T' represents the expected data interface for your component:

export class EditDialogComponent extends DialogBase<EditDialogData> {

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Data fetched by Next.js is failing to display on the web page

After writing a fetch command, I was able to see the data in the console.log but for some reason it is not showing up in the DOM. export default async function links(){ const res = await fetch('https://randomuser.me/api/'); const data = ...

What causes the Cassandra client driver to provide more detailed information compared to cqlsh?

I'm currently utilizing the datastax nodejs-driver to retrieve information about a keyspace from cassandra. const results = await client.execute( ` DESC KEYSPACE ${keyspace} ` ); The method client.execute provides a comprehensive object containin ...

"Incorporating the node_modules folder into the Express.js compilation process

Is there a way to automatically include dependencies during Express.js compilation, similar to building a React project? I want to avoid dealing with dependencies after the build process. Any suggestions on how to achieve this? I have not attempted any so ...

Ways to verify if the current date exists within a TypeScript date array

I am trying to find a way in typescript to check if the current date is included in a given array of dates. However, even after using the code below, it still returns false even when the current date should be present within the array. Can anyone please pr ...

The 'posts' binding element is assumed to have a type of 'any' by default

Currently, I'm working on a code project that involves graphql, react, and typescript. In the middle of the process, I encountered an error message stating "Binding element 'posts' implicitly has an 'any' type." I am unsure about w ...

How can we ensure that only one of two props is specified during compilation?

I've designed a customized Button component. interface Button { href?: string; action(): void; } I'm looking to ensure that when a consumer uses this Button, they can only pass either href or action as a prop, not both. I want TypeScri ...

The functionality of TypeScript's instanceof operator may fail when the method argument is not a simple object

There seems to be an issue with a method that is being called from two different places but returns false for both argument types. Despite checking for the correct types, the problem persists and I am unsure why. Although I have read a similar question on ...

Issue with Pagination in Angular 7: Functioning Error

I am having trouble with my pagination setup. I am struggling to understand how to properly pass this.total = res.totalPage; from the Component to the Service so that it can count the pages correctly. Currently, it is only displaying one page as shown in t ...

Is ngModel the appropriate method for connecting a form to server-side scripts?

Just diving into the world of Angular, I'm embarking on my very first project - a hybrid mobile app using Ionic/Angular. Within my app, each user has their unique notification settings. There are ten different types of notifications that users can to ...

Are there any potential performance implications to passing an anonymous function as a prop?

Is it true that both anonymous functions and normal functions are recreated on every render? Since components are functions, is it necessary to recreate all functions every time they are called? And does using a normal function offer any performance improv ...

Ways to "Compile out" log commands

In my typescript project, there is a section of code dedicated to creating debug information. However, upon profiling the application, I discovered that this debug code is causing a significant performance impact. Currently, my approach involves setting a ...

What is the best way to retrieve the outcome from the ngbModal component?

I'm seeking assistance with retrieving results from the ngbModal component. I trigger the modal with a link. <a class="order-collection-options-link" (click)="openTimePicker()">{{'ORDER_COLLECTION_OPTIONS_LABEL' | dict}}</a> ...

Prevent clicking on cells in the ng-zoro nz-calendar

Hello, I am using a nz-calendar and I need help disabling clicks on cells. <nz-calendar [(ngModel)]="date" [(nzMode)]="mode" > <div *nzDateCell="let date" class="date-cell"> <ng ...

The reset function in Angular's template-driven form does not seem to be functioning properly when implemented using a component

Form Template Example <form #contactFormTemplate = "ngForm" (ngSubmit)="submitContactForm()"> <input type="text" class="form-control" name="name" [(ngModel)]="formData.name" ...

Encountered an error with ng build --prod while attempting to import a JavaScript file within the app module

Is it possible to import a javascript file into my app module without access to the ts file? import { OtherComponent } from './node_modules/blahblah/OtherComponent.js' While trying to declare this component in @NgModule and running "ng build -- ...

When the promise is resolved, the members of the AngularJS controller are now

I'm experiencing some unexpected behavior in my controller when executing a certain method. The code snippet looks something like this: this.StockService.GetByInvoicesID(this.SelectedInvoice.ID).success((StockItems) => { this.StockItems = Stoc ...

Tips for choosing a specific quantity and adjusting its value

Just starting out with Ionic 3 and looking for some help with the code. Can anyone assist me in understanding how to change the value of an item in a shopping cart and have the subtotal reflect that change? cart.ts private _values1 = [" 1 ", "2", " 3 "," ...

Leveraging non-ionic-native Cordova plugin

I'm currently working on integrating the [This]https://github.com/louisbl/cordova-plugin-locationservices plugin into my Ionic 4 app. Since it's a non-Ionic-native plugin, what is the proper way to call its functions within my TypeScript code? ...

Encountering issues with MatTable functionality in Angular version 10

Could it be that I’m starting this project from scratch using Angular Material 10, a framework I’m not familiar with yet, or am I simply missing something? My mat-table isn’t showing up on the page at all, which is completely new to me. Here’s the ...

Having trouble with the Angular router link suddenly "failing"?

app.routes.ts: import { environment } from './environment'; import { RouterModule } from "@angular/router"; import { ContactUsComponent } from './static/components/contact-us.component'; import { HomeComponent } ...