Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reusing existing Angular Component inside material Dialog

I have an existing component ResultGridComponent that is passed data by @Input(). I want to use the same component for the MatDialog. Hence I added @Inject(MAT_DIALOG_DATA) data in the constructor of the ResultGridComponent component.

constructor(private spinner: EdpLoaderService, private dialog: MatDialog, @Optional() @Inject(MAT_DIALOG_DATA) data) {}

But when the component is called as per it's regular usage that is not as a dialog, I get the following error :

ERROR Error: StaticInjectorError(AppModule)[ResultGridComponent -> InjectionToken MatDialogData]: StaticInjectorError(Platform: core)[ResultGridComponent -> InjectionToken MatDialogData]: NullInjectorError: No provider for InjectionToken MatDialogData!

I am pretty sure I have imported all the needed modules. Because I created a separate component for the dialog and passed data to it and it worked fine. But I want to reuse the component. And I am pretty sure this error is coming when I call constructor the of the child component as a regular component and the constructor doesn't get the MatDialogData passed to it by the caller.

like image 703
Satvir Singh Avatar asked Oct 17 '25 04:10

Satvir Singh


2 Answers

In some cases, I would use @Optional() before the @Inject(MAT_DIALOG_DATA).

  constructor(
    @Optional() @Inject(MAT_DIALOG_DATA) dialogData: any
  ) {
    if (dialogData) {
     // here pass dialog data to the child component
    }
  }
like image 171
Stan Avatar answered Oct 18 '25 22:10

Stan


I was able to find a solution to the situation.


Problem Statement: I was trying to use the existing component (Let's call it ChildComponent) in 2 separate places. One as a regular child component and second, as a component inside Material Dialog.


Challenge: To pass data to the dialog component, we need @Inject(MAT_DIALOG_DATA) in the Child Component. But when you inject the ChildComponent inside the regular component, you don't provide any provider for the '@Inject(MAT_DIALOG_DATA)'. Hence, it fails while initiating. And we do need the '@Inject(MAT_DIALOG_DATA)' if we want to use the ChildComponent inside the Mat Dialog.


Solution: Create a wrapper component, let's call it (ChildWrapperComponent). For the regular use case, directly inject the ChildComponent in the parent component. Whereas for the Mat Dialog use case, provide the ChildWrapperComponent

const dialogRef  = this.dialog.open(ChildWrapperComponent, {
                 width: '90%',
                 disableClose: false,
                 data: {
                   fileName: this.fileName,
                   results: this.results
                 }
               } );

Now you can have the data inside the ChildWrapperComponent using @Inject(MAT_DIALOG_DATA) data

constructor(private spinner: EdpLoaderService, private dialog: MatDialog,
@Inject(MAT_DIALOG_DATA) data,
private dialogRef: MatDialogRef<ChildWrapperComponent>) {
this.setInputData(data);

}

Once you have the data inside the ChildWrapperComponent, inject the Child Component inside the Wrapper and pass data using @Input().

I am a newbie in Angular. Would highly appreciate better or different solutions.

like image 38
Satvir Singh Avatar answered Oct 18 '25 22:10

Satvir Singh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!