Angular 8通用输入组件开发报错:TypeError: this.form.get is not a function
解决Angular通用输入组件的
TypeError: this.form.get is not a function问题 嘿,我来帮你搞定这个通用输入组件的bug!先拆解下你遇到的核心问题,再一步步给出修复方案。
错误根源分析
你碰到的TypeError: this.form.get is not a function,本质是两个关键错误导致的:
- 表单组传递错误:父组件里给
inputFieldParams.formGroup传的是字符串'signUpForm',但Angular的[formGroup]指令需要的是实际的FormGroup实例,不是字符串名称,这直接导致框架找不到对应的表单对象。 - 响应式表单与ngModel混用:你在子组件模板里同时用了
formControlName和[(ngModel)],这在Angular响应式表单体系里是冲突的——响应式表单应该完全由FormControl管理值,不需要ngModel介入。
分步修复方案
第一步:修正父组件的参数传递
把formGroup的字符串值换成实际的FormGroup实例,同时把disabled的字符串'false'改成布尔值false(因为[disabled]需要布尔类型):
<form class="" [formGroup]="signUpForm"> <app-input-field [inputFieldParams]=" { type: 'text', class: 'form-control rounded-0', label: 'First Name', placeholder: 'First Name', formControlName: 'first_name', id: 'first_name', mode: '', formGroup: signUpForm, <!-- 去掉引号,传实例 --> value: pageMode != 'addMode' ? userData.first_name : '', disabled: false <!-- 改成布尔值 --> }" (getInputValueOnChange)="setInputValueOnChange('first_name', $event)"> </app-input-field> <show-errors [control]="signUpForm.controls.first_name"></show-errors> </form>
第二步:重构子组件模板,移除ngModel
完全用响应式表单的逻辑管理输入值,同时把所有属性绑定改成方括号[]的形式(更规范的Angular属性绑定写法):
<div [formGroup]="inputFieldParams.formGroup" class="input-group"> <label [for]="inputFieldParams.id"> {{ inputFieldParams.label }} <span *ngIf="inputFieldParams.required" class="required">*</span> </label> <input [formControlName]="inputFieldParams.formControlName" [type]="inputFieldParams.type" [class]="inputFieldParams.class" [placeholder]="inputFieldParams.placeholder" [id]="inputFieldParams.id" (change)="onChangeInput($event.target.value)" [disabled]="inputFieldParams.disabled"> </div>
第三步:完善子组件TS逻辑
给inputFieldParams定义明确的类型(避免any),并在ngOnInit里处理初始值和禁用状态:
import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core'; import { FormGroup } from '@angular/forms'; export class InputFieldComponent implements OnInit { @Input() inputFieldParams: { type: string; class: string; label: string; placeholder: string; formControlName: string; id: string; mode?: string; formGroup: FormGroup; value?: string; disabled: boolean; required?: boolean; }; @Output() getInputValueOnChange = new EventEmitter<string>(); constructor() { } ngOnInit(): void { // 初始化输入值(通过FormControl设置,符合响应式表单规范) if (this.inputFieldParams.value) { this.inputFieldParams.formGroup.get(this.inputFieldParams.formControlName)?.setValue(this.inputFieldParams.value); } // 设置禁用状态 const control = this.inputFieldParams.formGroup.get(this.inputFieldParams.formControlName); this.inputFieldParams.disabled ? control?.disable() : control?.enable(); } onChangeInput(value: string): void { this.getInputValueOnChange.emit(value); } }
进阶优化建议(可选)
为了让组件更易维护,建议把大对象inputFieldParams拆分成单独的@Input属性,这样API更清晰,类型检查更严格:
// 子组件TS import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core'; import { FormGroup } from '@angular/forms'; export class InputFieldComponent implements OnInit { @Input() formGroup: FormGroup; @Input() formControlName: string; @Input() type: string = 'text'; @Input() className: string = ''; // 避免和关键字class冲突 @Input() label: string = ''; @Input() placeholder: string = ''; @Input() id: string = ''; @Input() required: boolean = false; @Input() disabled: boolean = false; @Input() initialValue?: string; @Output() valueChange = new EventEmitter<string>(); constructor() { } ngOnInit(): void { if (this.initialValue) { this.formGroup.get(this.formControlName)?.setValue(this.initialValue); } this.setDisabledState(); // 自动监听值变化,无需手动绑定change事件 this.formGroup.get(this.formControlName)?.valueChanges.subscribe(value => { this.valueChange.emit(value); }); } private setDisabledState(): void { const control = this.formGroup.get(this.formControlName); this.disabled ? control?.disable() : control?.enable(); } }
对应的父组件调用也会更简洁:
<form class="" [formGroup]="signUpForm"> <app-input-field [formGroup]="signUpForm" [formControlName]="'first_name'" [type]="'text'" [className]="'form-control rounded-0'" [label]="'First Name'" [placeholder]="'First Name'" [id]="'first_name'" [initialValue]="pageMode != 'addMode' ? userData.first_name : ''" [disabled]="false" [required]="true" (valueChange)="setInputValueOnChange('first_name', $event)"> </app-input-field> <show-errors [control]="signUpForm.controls.first_name"></show-errors> </form>
内容的提问来源于stack exchange,提问作者Sandhu
相关产品推荐
相关产品推荐

