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

Angular中从服务获取用户数据动态赋值FormGroup及报错解决

问题根源

你的报错来自两个核心问题:

  • 执行时序错乱:构造函数中调用的接口是异步请求,ngOnInit初始化表单时,接口响应还没返回,此时this.me为undefined,直接读取this.me.lastname等属性本身就会触发空值错误。
  • 表单初始状态异常:你一开始将signupForm初始化为空的FormGroup,模板首次渲染时找不到lastname/firstname/email这些控件,直接抛出找不到控件的错误。另外你报错信息里的firsname是拼写失误,检查模板里是否有手误拼错控件名的情况。
修复方案

不要在初始化表单时直接绑定尚未获取到的接口数据,遵循「先初始化完整表单结构 -> 再请求接口 -> 最后用patchValue赋值」的流程即可:

  1. 移除类属性上初始化的空FormGroup,在ngOnInit中优先构建带空默认值的完整表单,保证模板渲染时所有控件都已存在。
  2. 表单初始化完成后再调用用户信息接口。
  3. 接口返回数据后,调用响应式表单的patchValue方法批量给控件赋值,不要在构建表单时直接引用未赋值的this.me属性。

修复后的完整TS代码如下:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
// 保留你原有的MeService、Me类型等导入

@Component({
  selector: 'app-user-profile', // 替换为你自己的组件选择器
  templateUrl: './form.html'
})
export class UserProfileComponent implements OnInit {
  me!: Me;
  signupForm!: FormGroup;

  constructor(
    private meService: MeService,
    private fb: FormBuilder
  ) {}

  ngOnInit(): void {
    // 先初始化完整表单,所有控件先用空字符串作为默认值
    this.signupForm = this.fb.group({
      lastname: [
        '',
        [
          Validators.required,
          Validators.maxLength(30),
          Validators.minLength(2),
          Validators.pattern("^[a-zA-Z éèàâëê'-]+$"),
        ]
      ],
      firstname: [
        '',
        [
          Validators.required,
          Validators.maxLength(30),
          Validators.minLength(2),
          Validators.pattern("^[a-zA-Z éèàâëê'-]+$"),
        ]
      ],
      email: [
        '',
        [
          Validators.required,
          Validators.email,
        ],
      ],
    });

    // 表单结构就绪后再请求用户数据
    this.CurrentUser();
  }

  CurrentUser(){
    this.meService.me().subscribe(
      result => {
        this.me = result;
        // 接口返回后给表单批量赋值
        this.signupForm.patchValue({
          lastname: this.me.lastname,
          firstname: this.me.firstname,
          email: this.me.email
        });
      }
    ) 
  }

  // 控件getter保持原有逻辑即可
  get lastname(): FormControl {
    return this.signupForm.get('lastname') as FormControl;
  }

  get firstname(): FormControl {
    return this.signupForm.get('firstname') as FormControl;
  }

  get email(): FormControl {
    return this.signupForm.get('email') as FormControl;
  }

  // 补充表单提交方法
  onSubmit() {
    if (this.signupForm.invalid) return;
    // 调用保存接口,传this.signupForm.value即可
  }
}

可选优化

如果不想让用户看到输入框先显示空值、再填充用户数据的闪烁效果,可以在表单标签上加判断,等用户数据加载完成后再渲染表单,同时记得给submit按钮绑定提交事件:

<form [formGroup]="signupForm" *ngIf="me" (ngSubmit)="onSubmit()">
    <div class="container">
        <!-- 你原有的表单项内容无需修改 -->
        <div class="form-group mb-5">
            <label for="exampleInputEmail1">Nom :</label>
            <div class="d-flex align-items-center">
                <input type="text" class="form-control" formControlName="lastname">
                <i class="fa-solid fa-lock pl-3"></i>
            </div>
        </div>
        <div class="form-group mb-5">
            <label for="exampleInputEmail1">Prenom :</label>
            <div class="d-flex align-items-center">
                <input type="text" class="form-control" formControlName="firstname">
                <i class="fa-solid fa-lock pl-3"></i>
            </div>
        </div>
        <div class="form-group mb-5">
            <label for="exampleInputEmail1">Email :</label>
            <div class="d-flex align-items-center">
                <input type="email" class="form-control" formControlName="email" id="exampleInputEmail1" aria-describedby="emailHelp">
                <i class="fa-solid fa-lock pl-3"></i>
            </div>
        </div>
        <button type="submit" class="btn btn-primary">Sauvegarder</button>
    </div>
</form>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 09:30:39