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

Angular:如何将AllDemande完整数据填充到FormGroup并实现全字段更新

Angular FormGroup 整合完整对象数据解决方案

核心问题分析

当前requestApproveForm仅手动配置了Id、reason、status三个字段,无法携带接口返回的AllDemande完整属性提交更新;同时存在异步数据加载与表单初始化时机不匹配的问题,可能导致数据填充失败。

解决方案步骤

  1. 同步异步数据与表单初始化时机:确保接口数据返回后再初始化或更新表单,避免空值填充
  2. 动态构建FormGroup控件:遍历AllDemande所有属性自动生成表单控件,无需手动逐个添加
  3. 批量填充表单数据:使用patchValue方法将完整数据批量注入表单,替代逐个控件赋值
  4. 保留只读字段:通过隐藏控件携带无需编辑的字段,保证提交数据的完整性

修改后的组件TS代码

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { DemandeConges } from 'src/app/models/ui-models/Demande_Conges';
import { CongesService } from '../../conges.service';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-print',
  templateUrl: './print.component.html',
  styleUrls: ['./print.component.scss']
})
export class PrintComponent implements OnInit {
  show: boolean = false;
  url: string='';
  report: string='';
  AllDemande: DemandeConges = {} as DemandeConges;
  errorMsg: string='';
  isRequestEdit = false;
  requestApproveForm !: FormGroup;
  has_error = false;
  approve_leave_update_msg: string='';
  submitted = false;

  demandeCongeId:string|null|undefined;

  constructor(
    private readonly congeService:CongesService,
    private formBuilder: FormBuilder,
    private readonly route: ActivatedRoute
  ) {}

  ngOnInit(): void {
    this.route.paramMap.subscribe((params) => {
      this.demandeCongeId = params.get('id');
      if(this.demandeCongeId){
        this.congeService.DemandeConge(this.demandeCongeId)
          .subscribe((successResponse)=> {
            this.AllDemande = successResponse;
            // 数据返回后若处于编辑状态,立即更新表单
            if (this.isRequestEdit) {
              this.initRequestApproveForm();
            }
          });
      } 
    });
  }

  initRequestApproveForm() {
    const formControls: {[key: string]: any} = {};
    // 遍历AllDemande属性生成表单控件
    Object.keys(this.AllDemande).forEach(key => {
      formControls[key] = key === 'status' 
        ? [this.AllDemande[key as keyof DemandeConges], Validators.required]
        : [this.AllDemande[key as keyof DemandeConges]];
    });
    // 确保reason字段存在(根据实际模型调整)
    if (!formControls['reason']) {
      formControls['reason'] = [''];
    }

    this.requestApproveForm = this.formBuilder.group(formControls);
  }

  toggleEdit() {
    this.isRequestEdit = !this.isRequestEdit;
    // 数据加载完成后才初始化表单
    if (this.isRequestEdit && Object.keys(this.AllDemande).length > 0) {
      this.initRequestApproveForm();
    }
  }

  get f() { return this.requestApproveForm.controls; }

  onSubmit(){
    this.submitted = true;
    if (this.requestApproveForm.invalid) {
      return;
    }
    // 提交完整表单数据
    this.congeService.updateDemandeConges(this.demandeCongeId, this.requestApproveForm.value).subscribe(res => {
      this.has_error = false;
      this.approve_leave_update_msg = '提交成功';
      this.AllDemande = res;
      this.submitted = false;
      this.isRequestEdit = false;
    }, error => {
      this.has_error = true;
      this.approve_leave_update_msg = '提交失败:' + error.message;
    })
  }
}

修改后的HTML模板

<div class="container">
  <div class="row">
    <div class="col-md-6 ">
      <div class="profile-head">
        <h1 class="display-3">Nom et Prénom : {{AllDemande.employeeNom}} {{AllDemande.employeePrenom}} </h1>
        <h3>Date de la Demande :{{AllDemande.created_AT|date:'dd-MM-yyyy'}} </h3>
      </div>
    </div>
    <div class="col-md-6 ">
      <button class="btn btn-info float-right" (click)="toggleEdit()">
        {{isRequestEdit ? "Afficher la Demande" : "Approbation de la demande"}}
      </button>
    </div>
    <div mat-tab-nav-bar class="custom-tab">
      <a mat-tab-link class="nav-link active">Info</a>
    </div>
  </div>
  <div class="row">
    <div class="col-md-5">
      <div class="col-md-6 border-right ">
        <h3 class="pl-2">LeaveRequest Id : {{AllDemande.id}} </h3>
        <h3 class="pl-2">Employee : {{AllDemande.employeeNom}} {{AllDemande.employeePrenom}} </h3>
        <h3 class="pl-2">Type de Congé : {{AllDemande.typeCongesId}} </h3>
        <h3 class="pl-2">Nombre des jours : {{AllDemande.nmbJours}} Jours</h3>
        <h3 class="pl-2">Date début du congé : {{AllDemande.from_Date|date:'dd-MM-yyyy'}}</h3>
        <h3 class="pl-2">Date Fin du congé : {{AllDemande.to_Date|date:'dd-MM-yyyy'}} </h3>
        <h3 class="pl-2">Status :{{AllDemande.status}}</h3>
        <h3 class="pl-2">Alternative :{{AllDemande.alternate}}</h3>
        <h3 class="pl-2">Coordonnées :{{AllDemande.details}}</h3>
      </div>
      <button (click)="Clicked(AllDemande.id)">Télécharger la Demande</button>
      <div *ngIf="show">
        <iframe id="report" height="1000" width="100%" [src]="url | safeUrl"></iframe>
      </div>
    </div>

    <div class="col-sm-1">
      <div class="d-flex" style="height: 360px;">
        <div class="vr"></div>
      </div>
    </div>

    <div class="col-sm-6">
      <div *ngIf="isRequestEdit" class="col-md-9">
        <form [formGroup]="requestApproveForm" (ngSubmit)="onSubmit()" >
          <div *ngIf="!!approve_leave_update_msg" [ngClass]="has_error ? 'alert alert-danger': 'alert alert-info'">{{approve_leave_update_msg}}</div>

          <h5 class="text-center text-info mb-4"> Approve Request </h5>

          <!-- 隐藏控件:携带所有只读字段 -->
          <input type="hidden" formControlName="id">
          <input type="hidden" formControlName="employeeNom">
          <input type="hidden" formControlName="employeePrenom">
          <input type="hidden" formControlName="typeCongesId">
          <input type="hidden" formControlName="nmbJours">
          <input type="hidden" formControlName="from_Date">
          <input type="hidden" formControlName="to_Date">
          <input type="hidden" formControlName="alternate">
          <input type="hidden" formControlName="details">
          <input type="hidden" formControlName="created_AT">

          <!-- 可编辑字段:status -->
          <div class="form-group row" >
            <label for="status" class="col-sm-3 col-form-label" >Status &nbsp;<span class="text-danger">* </span></label>
            <div class="col-sm-6">
              <mat-radio-group id="status" formControlName="status" class="custom-ngSelect">
                <mat-radio-button value="APPROUVÉ">APPROUVÉ</mat-radio-button>
                <mat-radio-button class="pl-2" value="REFUSÉ">REFUSÉ</mat-radio-button>
              </mat-radio-group>
            </div>
          </div>

          <!-- 可编辑字段:reason -->
          <div class="form-group row">
            <label for="reason" class="col-sm-3 col-form-label">Reason&nbsp;</label>
            <div class="col-sm-9">
              <input type="text" id="reason" formControlName="reason" class="form-control" placeholder="Reason" />
            </div>
          </div>

          <button mat-raised-button color="primary" class="mt-3 btn-block" type="submit">Submit </button>
        </form>
      </div>
    </div>
  </div>
</div>

关键说明

  • 强类型优化:将AllDemande指定为DemandeConges类型,避免any类型隐患,同时简化属性遍历逻辑
  • 动态表单构建:通过Object.keys自动生成控件,后续模型字段变更无需手动修改表单配置
  • 异步时机处理:接口数据返回后再初始化表单,确保数据填充有效;切换编辑状态时也会检查数据加载状态
  • 隐藏控件设计:通过隐藏input携带只读字段,保证提交数据包含AllDemande完整属性,满足后端更新需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 06:20:54