Accessing Subcomponent Methods in Angular 5: a guide for calling subcomponent functions from a parent component's HTML template

My DeleteAssociationDialog subcomponent contains a method called openDeleteAssociationDialog:

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');
    });
  }
}

I want to display the dialog when clicking on a button in the parent component's (app.component) HTML. I am using @ViewChild to create 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;
}

An error is occurring -- "ERROR TypeError: Cannot read property 'openDeleteAssociationDialog' of undefined"

What could be causing this error? How should I correctly reference a subcomponent method from a parent component's HTML template?

Answer №1

One issue arises from the method to open the dialog being enclosed within the dialog itself. This means the method is only accessible once the dialog is already opened, creating a bit of a catch-22 situation.

The solution is to relocate the

openDeleteAssociationDialogComponent
method to the parent component.

Once that's done, it becomes quite straightforward:

<button (click)="openDeleteAssociationDialogComponent()"></button>

If you want to make the dialog-opening button reusable by abstracting it away, you can follow a structure like this:

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');
    });
  }
}

Now, you can easily reuse the button responsible for opening the delete association dialog.

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

Ways to modify the text color of a dropdown button upon clicking by leveraging ViewChild and ElementRef techniques

I'm attempting to change the color of text in my dropdown menu button after it's clicked using @Viewchild and elementRef. However, the method I've tried doesn't seem to be working as expected. <div class="dropdown"> ...

Angular: The property 'data' is not defined and cannot be read

HomeComponent.html:16 ERROR TypeError: Cannot read property 'data' of undefined at Object.eval [as updateDirectives] (HomeComponent.html:16) at Object.debugUpdateDirectives [as updateDirectives] (core.es5.js:13067) at checkAndUpdateVi ...

Add a new module to your project without having to rely on the initial

I'm looking to experiment with a module by making some adjustments for testing purposes. You can find the code here. Currently, all I need to do is type "npm install angular2-grid" in my terminal to add it to my project. Here's my concern: If ...

When using primeng, it is necessary to place the hyphen on the parent node when selecting a child element

https://i.sstatic.net/KM8Fo.png This code is written in Typescript. //DECLARATIONS AND CODE Ngonint--> ngOnInit() { if(this.title === "Create"){ this.dataProfilo = {} this.dataProfilo.function = []; this.ser ...

The NgIf directive is triggered, but the element remains hidden. It is unclear whether it briefly appears and then disappears, or if it never shows up at all

Having trouble with the element marked with ***. My goal is to create and fill the item-list with ion-items, but I encountered duplicate entries. To resolve this issue, I tried using a flag called hall.show. The console.log confirms that the show attribute ...

Upload images using Ionic 3 from both camera and gallery seamlessly

Could you please assist with an issue I'm encountering in my ts file code? I am having difficulty sending an image to the server. Although it appears to be working as I receive a notification stating that the image has been successfully uploaded, I am ...

Utilizing an array for substituting sections of a string: a guide

I have an array of values like ['123', '456', '789']. What is the best way to iterate over this array and update parts of a string that contain the text :id in sequence (e.g. users/:id/games/:id/server/:id)? Currently, I&apos ...

React Native bottom tab navigator not changing between tabs

Hi, I'm new to React Native and I think I might have a structural issue because I can't figure out what I'm doing wrong. I'm trying to create 4 tabs, but when I click on each tab, it doesn't take me to the next page. Nothing happe ...

The property 'nometape' cannot be assigned to an undefined value

Currently, I'm encountering an issue in my Angular 7 code where it states "cannot set property 'nometape' of undefined." The problem lies within the initialization process of my interface "Process" which contains an array of objects called " ...

Utilize the click spinner feature on a single button in Angular

I have a table with a list of items and each item has a button to request a PDF document from the server. I want to show a spinner while waiting for the document to be received. Currently, when I click on a button, the spinner appears on all buttons instea ...

After closing and reopening the app, I noticed that the ionic slider images fail to display until I navigate to the next page

//// How can I retrieve the data for (let i = 0; i < res.length; i++) { let item: any = {}; item.slide = res.item(i).slide; items.push(item); } this.productsService.setSlideList = items; setTimeout(() => { this.sliderImage = items; consol ...

Issues with expected identifiers and type mismatch errors encountered when defining a TypeScript class

As someone who is still relatively new to coding, I am facing a challenge while trying to create a TypeScript class within an Angular project that is based on a complex JSON file. The issue arises from the way the properties were defined in the JSON using ...

Angular ngFor directive is used to iterate over a collection and display each record

Hey there! I am currently facing an issue where the data array is displaying on the console, but only one record is being displayed in the view. users: any[]=[]; ngOnInit(): void { this.loadUsers(); } loadUsers() { let controller = this; t ...

What steps should I follow to include Sass compilation in my Angular CLI 6 project in the angular.json file?

I recently started working on a project in Angular using the latest version of Angular CLI 6.0. However, I need to enable Sass compilation for my existing project. Typically, you can specify this during project creation, but since mine is already set up wi ...

Is there a way to update the data on a view in Angular 9 without the need to manually refresh the page?

Currently, I am storing information in the SessionStorage and attempting to display it in my view. However, there seems to be a timing issue where the HTML rendering happens faster than the asynchronous storage saving process. To better illustrate this com ...

When any part of the page is clicked, the data on the Angular page will automatically

Clicking the mouse anywhere on the page, even in a blank spot, causes the data array to resort itself. I understand that clicking may trigger a view change if an impure pipe is set, but I have not used one. So I am puzzled because my development testing ...

reorganizing groupby collection of objects using es6

I have received a data response that needs to be formatted as expected. I need to format an array of objects based on the rowIndex, and I am open to any better solutions. Input : productdata:[ { rowIndex:1 , columnKey:'productName'}, ...

Encountering the error message "React child is not valid as a Gatsby wrapRootElement" while using TypeScript with Gatsby

I've been exploring ways to implement a theme provider in Gatsby using the wrapRootElement browser API. However, I seem to have hit a roadblock as I keep encountering an error message that says "Objects are not valid as a React child (found: object wi ...

The alignment of navbar links to the right is off in Bootstrap 4 and Angular 5

https://i.sstatic.net/UacKS.pngI am having an issue while working on my first application using bootstrap 4 and angular 5. The navbar links that should be aligned to the right are appearing on the left side instead. <nav class="navbar navbar-expand-md ...

Getting started with TypeScript and Azure CLI's 'az acr' command

Currently, I am in the process of developing a custom task for Azure DevOps Server 2019. While I have successfully created a .ps1 script for Windows, I am facing challenges with Linux. To tackle this, I have opted to write the script in TypeScript as I fin ...