Angular 7+ ng-template内按Enter切换输入框出现focus未定义报错
问题根源
你遇到的Cannot read properties of undefined (reading 'focus')错误,核心原因是**<ng-template>是惰性加载的模板片段,内部的模板引用变量(#input2)无法被组件外部或未实例化的模板上下文访问**,同时你的@ViewChild('input2')也无法获取到未渲染的模板内元素,导致nextField或this.input2均为undefined。
解决方案
步骤1:确保<ng-template>被实例化
首先必须让<ng-template>的内容渲染到DOM中,可使用ngTemplateOutlet指令实现:
<!-- 渲染myTemplate的内容到DOM --> <ng-container *ngTemplateOutlet="myTemplate"></ng-container> <ng-template #myTemplate> <table> <tr> <td> <input (keydown.enter)="onEnterPressed($event, input2)" #input1 /> </td> </tr> <tr> <td> <input #input2 /> </td> </tr> </table> </ng-template>
步骤2:调整组件逻辑(二选一即可)
方案A:利用模板内部引用变量传递(推荐)
模板实例化后,内部的input2引用变量在模板上下文内可正常访问,只需在组件方法中增加空值判断避免报错:
import { Component, ElementRef } from '@angular/core'; @Component({ selector: 'app-your-component', templateUrl: './your-component.component.html', }) export class YourComponent { onEnterPressed(event: KeyboardEvent, nextField?: ElementRef): void { if (event.key === 'Enter' && nextField?.nativeElement) { event.preventDefault(); nextField.nativeElement.focus(); } } }
方案B:通过@ViewChild获取元素(适合复杂场景)
如果需要在组件类中主动控制焦点,可使用@ViewChild(Angular 8+默认static: false),同时确保模板已渲染:
import { Component, ViewChild, ElementRef } from '@angular/core'; @Component({ selector: 'app-your-component', templateUrl: './your-component.component.html', }) export class YourComponent { @ViewChild('input2') input2?: ElementRef; onEnterPressed(event: KeyboardEvent): void { if (event.key === 'Enter' && this.input2?.nativeElement) { event.preventDefault(); this.input2.nativeElement.focus(); } } }
对应模板修改为:
<ng-container *ngTemplateOutlet="myTemplate"></ng-container> <ng-template #myTemplate> <table> <tr> <td> <input (keydown.enter)="onEnterPressed($event)" #input1 /> </td> </tr> <tr> <td> <input #input2 /> </td> </tr> </table> </ng-template>
关键说明
<ng-template>本身不会渲染内容,必须通过ngTemplateOutlet、*ngIf等指令触发实例化,内部元素才会被添加到DOM。- 模板引用变量的作用域仅限于定义它的模板内部,外部无法直接访问,需确保在同一模板上下文内传递或获取。
内容的提问来源于stack exchange,提问作者Sakib
相关产品推荐
相关产品推荐

