【问题标题】:Angular 5: how to refer to a subcomponent method from a parent component HTML template?Angular 5:如何从父组件 HTML 模板中引用子组件方法?
【发布时间】:2018-03-15 14:07:15
【问题描述】:

我有一个对话框子组件 DeleteAssociationDialog,其中包含一个 openDeleteAssociationDialog 方法:

删除关联-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');
    });
  }
}

当点击父组件(app.component)HTML中的按钮时应该显示对话框,我正在使用@ViewChild建立引用:

app.component.html [片段]

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

出现错误—— "ERROR TypeError: Cannot read property 'openDeleteAssociationDialog' of undefined"

我错过了什么?如何正确引用父组件 HTML 模板中的子组件方法

【问题讨论】:

  • 你为什么要这样做?这听起来像是不好的做法
  • 请添加您的/app.component.html 代码
  • 这个想法是划分对话框组件,因为我真的不想在 app.component.ts 中有多个 @Component。我是 Angular 的新手,所以还不熟悉它的最佳实践,但是我在单个 app.component.ts 中的每个对话框都有多个 @ Component 似乎肯定是一种不好的做法:)
  • @OvidiuDolha 在调用方法的地方添加了它的片段
  • @porgo 我试过了,得到了'NullInjectorError: No provider for MatDialogRef!',我还读到对话框不需要它

标签: angular typescript angular5


【解决方案1】:

我认为问题源于打开对话框的方法包含在对话框本身中。因此,除非对话框已经打开,否则该方法将不存在……对话框组件既是鸡也是鸡蛋。

解决方法是将openDeleteAssociationDialogComponent的方法移到父级。

然后很简单:

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

如果您想将其抽象出来以使对话框打开按钮可重用,您可以执行以下操作:

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

然后您可以重复使用打开删除关联对话框的按钮。

【讨论】:

  • 我正在处理的问题是我无法从父组件 HTML 中引用子组件方法,也无法在父组件 HTML 中引用子组件选择器。看起来我正在做一些非惯用的方式,但我无法想象单个主组件的架构,从父组件 HTML 到子组件中的方法的点击引用是不寻常的。将所有对话框代码合并到一个组件中?
  • 您可以引用子组件方法,假设该方法是公共的并且子组件已定义。但是,您当前正在尝试调用对话框上的方法,该方法在打开之前不存在。请参阅我更新的答案,了解一些适合您的选项。
  • 很高兴我能提供帮助 - 考虑投票以表明它有帮助和/或将其标记为已接受,以便其他人知道您的问题已得到解答。欢迎来到 SO :)
猜你喜欢
  • 2018-09-15
  • 2019-01-09
  • 2023-01-08
  • 2018-07-15
  • 2021-10-27
  • 2019-04-03
  • 2018-09-12
  • 2018-07-01
  • 1970-01-01
相关资源
最近更新 更多