Reputation: 481
I have a dialog subcomponent DeleteAssociationDialog with an openDeleteAssociationDialog method in it:
delete-association-dialog.component.ts
import { Component } from '@angular/core';
import { MatDialog, MatDialogRef } from '@angular/material';
@Component({
selector: 'app-delete-association-dialog',
templateUrl: 'delete-association-dialog.component.html',
styleUrls: ['delete-association-dialog.component.css']
})
export class DeleteAssociationDialogComponent {
constructor(
public dialog: MatDialog,
public dialogRef: MatDialogRef<DeleteAssociationDialogComponent>) { }
openDeleteAssociationDialog(): void {
let dialogRef = this.dialog.open(DeleteAssociationDialogComponent, {
width: '250px'
});
dialogRef.afterClosed().subscribe(result => {
console.log('The dialog was closed');
});
}
}
The dialog should be shown when clicked on a button in the parent component (app.component) HTML, I am using @ViewChild to establish a reference:
app.component.html [fragment]
<button mat-icon-button color="warn" (click)="child.openDeleteAssociationDialog()">
<mat-icon>delete</mat-icon>
</button>
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material';
import { FormsModule } from '@angular/forms';
import { MatDialogModule } from '@angular/material';
import { AppComponent } from './app.component';
import { DeleteAssociationDialogComponent } from './delete-association-dialog/delete-association-dialog.component';
import { MatDialogRef} from '@angular/material/dialog'
@NgModule({
declarations: [
AppComponent,
DeleteAssociationDialogComponent,
],
entryComponents: [DeleteAssociationDialogComponent],
imports: [
BrowserModule,
NgModule,
BrowserAnimationsModule,
MatButtonModule,
MatInputModule,
FormsModule
MatDialogModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.ts
import { Component, ViewChild } from '@angular/core';
import { MatDialog, MatDialogRef } from '@angular/material';
import { DeleteAssociationDialogComponent } from './delete-association-dialog/delete-association-dialog.component';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css', './app.component.panel.css']
})
export class AppComponent {
@ViewChild('DeleteAssociationDialogComponent') child: DeleteAssociationDialogComponent;
}
Getting an error -- "ERROR TypeError: Cannot read property 'openDeleteAssociationDialog' of undefined"
What am I missing? How do I properly refer to a subcomponent method from a parent component HTML template?
Upvotes: 2
Views: 822
Reputation: 8306
I think the problem stems from the fact that the method to open the dialog is contained within the dialog itself. So that method won't exist unless the dialog is already opened...the dialog component is both the chicken and the egg.
The solution is to move the method to openDeleteAssociationDialogComponent
to the parent.
And then it's simple:
<button (click)="openDeleteAssociationDialogComponent()"></button>
If you want to abstract it away to make the dialog-opening button reusable, you can do something like:
component.html
<association-deleter></association-deleter>
component.ts
@Component({
selector: 'association-deleter',
template: `<button (click)="openDialog()"></button>`
})
export class DeleteAssociationComponent {
constructor(
public dialog: MatDialog,
public dialogRef: MatDialogRef<DeleteAssociationDialogComponent>
){}
openDeleteAssociationDialog(): void {
let dialogRef = this.dialog.open(DeleteAssociationDialogComponent, {
width: '250px'
});
dialogRef.afterClosed().subscribe(result => {
console.log('The dialog was closed');
});
}
}
Then you could reuse the button which opens the delete association dialog.
Upvotes: 2