I have a component A that should normally be displayed without a close button. However, when I open component A in a dialog, I want to add a Close Button to close the dialog.
How can I implement this behavior in Angular? Is there an elegant way to determine if the component is open in a dialog so I can add a Close Button accordingly?
Thanks in advance for your assistance!
Here is my code: https://stackblitz.com/edit/stackblitz-starters-p4pfnr?file=src%2Fapp%2Fb%2Fb.component.ts
FULL CODE:
popup html
<form [formGroup]="form" class="">
<h1>App A</h1>
<mat-form-field>
<mat-label>Email</mat-label>
<input
matInput
type="email"
formControlName="email"
placeholder="Ex. pat@example.com "
/>
</mat-form-field>
<button mat-button type="button" color="primary">Save</button>
</form>
popup ts
import { Component } from '@angular/core';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { FormControl, FormGroup } from '@angular/forms';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
@Component({
selector: 'app-a',
standalone: true,
imports: [
FormsModule,
ReactiveFormsModule,
MatFormFieldModule,
MatInputModule,
MatButtonModule,
],
templateUrl: './a.component.html',
styleUrl: './a.component.css',
})
export class AComponent {
form: FormGroup;
constructor() {
this.form = new FormGroup({
email: new FormControl(''),
});
}
}
calling ts
import { Component } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { AComponent } from '../a/a.component';
@Component({
selector: 'app-b',
standalone: true,
imports: [],
templateUrl: './b.component.html',
styleUrl: './b.component.css',
})
export class BComponent {
constructor(public dialog: MatDialog) {}
public openDialog() {
this.dialog
.open(AComponent, {})
.afterClosed()
.subscribe((res) => {
console.log(res);
});
}
}
calling html
<button (click)="openDialog()" mat-raised-button color="primary" type="button">
Open Dialog
</button>
Yes we can use the data
property of the second argument of open
method. we set a property fromPopup
as true and then read it on our component!
I use the angular decorator @Optional
so that even if we use this component outside of a popup, we still will not get dependency injection error for trying to get MAT_DIALOG_DATA
b ts
import { Component } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { AComponent } from '../a/a.component';
@Component({
selector: 'app-b',
standalone: true,
imports: [AComponent],
templateUrl: './b.component.html',
styleUrl: './b.component.css',
})
export class BComponent {
constructor(public dialog: MatDialog) {}
public openDialog() {
this.dialog
.open(AComponent, {
data: { fromPopup: true },
})
.afterClosed()
.subscribe((res) => {
console.log(res);
});
}
}
b html
<button (click)="openDialog()" mat-raised-button color="primary" type="button">
Open Dialog
</button>
<app-a />
a ts
import { Component, Inject, Optional } from '@angular/core';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { FormControl, FormGroup } from '@angular/forms';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-a',
standalone: true,
imports: [
FormsModule,
ReactiveFormsModule,
MatFormFieldModule,
MatInputModule,
MatButtonModule,
CommonModule,
MatDialogModule,
],
templateUrl: './a.component.html',
styleUrl: './a.component.css',
})
export class AComponent {
form!: FormGroup;
fromPopup = false;
constructor(
@Optional() @Inject(MAT_DIALOG_DATA) public data: { fromPopup: boolean }
) {
this.fromPopup = !!data?.fromPopup;
this.form = new FormGroup({
email: new FormControl(''),
});
}
}
a html
<form [formGroup]="form" class="">
<h1>App A</h1>
<mat-form-field>
<mat-label>Email</mat-label>
<input
matInput
type="email"
formControlName="email"
placeholder="Ex. pat@example.com "
/>
</mat-form-field>
<button mat-button type="button" color="primary">Save</button>
</form>
<button *ngIf="fromPopup" mat-button [mat-dialog-close]="true">
shows only for popup!
</button>