You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular组件调用子组件模板元素报错:Cannot read properties of undefined (reading 'pdfData')

问题:Angular父组件调用子组件模板元素时出现“Cannot read properties of undefined (reading 'pdfData')”错误

我有两个Angular组件:UserPatientsReportFormComponent(父组件)和UserPatientsReportFormTemplateComponent(子组件),想要在父组件中调用子组件的模板元素#pdfData,但报错“Cannot read properties of undefined (reading 'pdfData')”。以下是相关代码,需要修改方案:

子组件(UserPatientsReportFormTemplateComponent)模板代码

<div id="pdfData" #pdfData>
    <table  *ngFor="let hubxReport of hubxReportList; let i=index">
      <tr>
        <th>{{hubxReport.categoryName}} + "Test"</th>
      </tr>
      <tr>
        <th>{{column}}</th>
      </tr>
      <tr *ngFor="let item of hubxReport.hubxDataItems">
        <td></td>
        <td>{{item.itemTitle}}</td>
        <td>{{item.itemValue}}</td>
        <td>{{item.itemUnit}}</td>
        <td>{{item.normalRange}}</td>
      </tr>
    </table>
</div>

子组件(UserPatientsReportFormTemplateComponent)逻辑代码

export class UserPatientsReportFormTemplateComponent implements OnInit {

  clientId : number;
  hubxReportList : Array<HubxDataModel> = [];

  @ViewChild('pdfData') public pdfData: ElementRef;

  constructor(private activatedRoute: ActivatedRoute,private usersService: UsersService,private commonService:CommonService) { 

  }

  ngOnInit(): void {
    this.activatedRoute.queryParams.subscribe(params => {
      this.clientId = params.id == undefined ? null : this.commonService.encryptValue(params.id, false);
    });
    this.getHubxReport();
  }

  getHubxReport() {
    this.usersService.getHubxReport(this.clientId).subscribe((response: ResponseModel) => {
      if (response != null && response.data != null && response.data.length > 0) {
        this.hubxReportList = response.data;
      }
    });
  }

}

父组件(UserPatientsReportFormComponent)部分代码

export class UserPatientsReportFormComponent implements OnInit {
@ViewChild(UserPatientsReportFormTemplateComponent) userPatientReportFormTemplate: UserPatientsReportFormTemplateComponent; 
}

父组件中调用模板元素的函数代码

downloadPDF(isSubmit:any) {  
        let doc = new jsPDF();
        let rows: Array<any> = [];
        let header: Array<any> = [];
        let medicineInfo: any;
        let physicianInfo: any;
        let content= this.userPatientReportFormTemplate.pdfData.nativeElement; //---错误发生在这里---
        let _elementHandlers =  
        {  
          '#editor':function(element,renderer){  
            return true;  
          }  
        };  
        doc.fromHTML(content.innerHTML,15,15,{  
                'width':190,  
                'elementHandlers':_elementHandlers  
              }); 
}

修改方案

1. 确保父组件正确获取子组件实例

  • 若父组件模板中UserPatientsReportFormTemplateComponent是通过*ngIf等条件渲染的,需确保调用downloadPDF时组件已渲染完成;Angular 8+中@ViewChild默认static: false,会在视图初始化后获取实例。
  • 若组件是静态渲染(无条件渲染逻辑),可设置static: true确保在ngOnInit阶段就能获取实例:
@ViewChild(UserPatientsReportFormTemplateComponent, { static: true }) 
userPatientReportFormTemplate: UserPatientsReportFormTemplateComponent; 

2. 确保子组件的pdfData元素已初始化

子组件的@ViewChild('pdfData')会在ngAfterViewInit生命周期钩子后才完成初始化。如果父组件在ngOnInit中直接调用downloadPDF,此时子组件的pdfData可能还未就绪:

  • 确保downloadPDF通过用户交互触发(比如按钮点击),而非在组件初始化阶段自动执行;或在父组件的ngAfterViewInit中执行相关逻辑。

3. 子组件封装获取元素的方法(推荐)

遵循组件封装原则,不要直接访问子组件的属性,而是在子组件中暴露方法返回目标元素:

// 子组件新增方法
getPdfElement(): ElementRef | undefined {
  return this.pdfData;
}

父组件中调用该方法:

downloadPDF(isSubmit:any) {  
        const pdfElement = this.userPatientReportFormTemplate.getPdfElement();
        if (!pdfElement) {
          console.error('PDF元素未初始化');
          return;
        }
        let content = pdfElement.nativeElement;
        // 后续jsPDF逻辑不变
}

4. 确保异步数据加载完成后再生成PDF

子组件的表格内容依赖异步加载的hubxReportList,需确保数据加载完成后再执行PDF生成:

// 子组件中添加数据加载完成标志
isDataLoaded = false;

getHubxReport() {
    this.usersService.getHubxReport(this.clientId).subscribe((response: ResponseModel) => {
      if (response != null && response.data != null && response.data.length > 0) {
        this.hubxReportList = response.data;
        this.isDataLoaded = true; // 标记数据加载完成
      }
    });
}

父组件中先判断标志再执行:

downloadPDF(isSubmit:any) {  
        if (!this.userPatientReportFormTemplate?.isDataLoaded) {
          console.error('数据未加载完成,无法生成PDF');
          return;
        }
        // 后续逻辑不变
}

内容的提问来源于stack exchange,提问作者Manipuri Vlogs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 06:45:34