Angular中点击按钮时如何保存动态生成的多个表单数据到数据库
Angular中点击按钮时如何保存动态生成的多个表单数据到数据库
我看了你的代码,发现几个关键问题导致你没法把动态表单的数据成功保存到数据库,咱们一步步来调整:
1. 修正组件的提交逻辑:传递正确的数据格式
你现在的提交方法里,错误地把FormGroup数组直接传给了服务,但后端需要的是纯数据数组。另外你有两个重复的提交方法,我们可以整合为一个清晰的逻辑:
修改你的FetchDataComponent代码:
import { Component, OnInit } from '@angular/core'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; // 别忘了导入Validators import { AnimalService } from '../animal.service'; @Component({ selector: 'app-fetch-data', templateUrl: './fetch-data.component.html', }) export class FetchDataComponent implements OnInit { reactForm: FormGroup; public forms: FormGroup[] = []; public unitData: Object[] = [ { Id: 'Form1', Form: '1' }, { Id: 'Form2', Form: '2' }, { Id: 'Form3', Form: '3' }, { Id: 'Form4', Form: '4' }, { Id: 'Form5', Form: '5' }, ]; public val: string = "1"; public unitFields: Object = { text: 'Form', value: 'Form' }; public unitWaterMark: string = ''; ngOnInit(): void { this.generateForms(1); } generateForms(count: number): void { this.forms = []; for (let i = 0; i < count; i++) { this.forms.push( this.fb.group({ Id: [0], Animal: [null, Validators.required], // 增加必填验证 Tagno: [null, Validators.required], // 增加必填验证 }) ) } } dropdownChange(args: any): void { const selectedCount = parseInt(args.value, 10); if (!isNaN(selectedCount)) { this.generateForms(selectedCount); } } // 统一的提交方法 onSubmitAll() { let allValid = true; // 遍历表单,收集数据同时做验证 const allFormData = this.forms.map(form => { if (!form.valid) { form.markAllAsTouched(); allValid = false; } return form.value; }); if (allValid) { // 调用服务提交纯数据数组 this.service.postOffspring(allFormData).subscribe({ next: (response) => { console.log('所有表单数据保存成功!', response); // 成功后可以重置表单 this.generateForms(1); this.val = "1"; }, error: (error) => { console.error('保存失败,请检查后端接口', error); alert('保存失败,请稍后重试'); } }); } else { alert('请填写所有必填字段!'); } } constructor(private fb: FormBuilder, private service: AnimalService ) {} }
2. 调整服务的POST方法:支持接收数组
你的服务现在是按单个对象接收的,我们要改成支持接收多个表单的数据数组:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Offspring } from './animal'; @Injectable({ providedIn: 'root' }) export class AnimalService { readonly Urloffspring = 'api/AnimalAPI'; constructor(private http:HttpClient) { } formOffspring:Offspring = new Offspring(); formSubmitted: boolean = false; // 改成接收Offspring数组 postOffspring(offspringList: Offspring[]){ console.log('要提交的数组:', offspringList); return this.http.post<Offspring[]>(this.Urloffspring, offspringList); } }
同时确保你的Offspring模型类包含所有表单字段:
export class Offspring { Id: number; Animal: string; Tagno: string; constructor() { this.Id = 0; this.Animal = ''; this.Tagno = ''; } }
3. 给HTML加提交按钮和验证提示
在动态表单循环结束后,添加统一的提交按钮,同时给输入框加错误提示:
<div class="col-lg-12 control-section"> <div class="content-wrapper" style="max-width: 600px; margin: 0 auto;"> <ejs-dropdownlist id="Unt" [dataSource]="unitData" type="text" name="Unt" [fields]="unitFields" placeholder="选择表单数量" (change)="dropdownChange($event)" floatLabelType="Auto" [value]="val" > </ejs-dropdownlist><br><br> <div *ngFor="let form of forms; let i = index"> <form [id]="'formId' + i" [formGroup]="form" class="form-horizontal" novalidate> <div class="form-title"> <span>表单 {{ i + 1 }}</span> </div> <div class="form-group"> <div class="e-float-input"> <input [id]="'Id' + i" formControlName="Id" /> <span class="e-float-line"></span> <label [for]="'Id' + i" class="e-float-text">ID</label> </div> </div> <div class="form-group"> <div class="e-float-input"> <input [id]="'Animal' + i" type="text" formControlName="Animal" /> <span class="e-float-line"></span> <label [for]="'Animal' + i" class="e-float-text">Animal</label> <!-- 验证错误提示 --> <div *ngIf="form.get('Animal')?.invalid && (form.get('Animal')?.touched || form.get('Animal')?.dirty)" class="text-danger"> Animal为必填项 </div> </div> </div> <div class="form-group"> <div class="e-float-input"> <input [id]="'Tagno' + i" type="text" formControlName="Tagno" /> <span class="e-float-line"></span> <label [for]="'Tagno' + i" class="e-float-text">Tagno</label> <!-- 验证错误提示 --> <div *ngIf="form.get('Tagno')?.invalid && (form.get('Tagno')?.touched || form.get('Tagno')?.dirty)" class="text-danger"> Tagno为必填项 </div> </div> </div> </form> </div> <!-- 统一提交按钮 --> <button type="button" (click)="onSubmitAll()" class="btn btn-primary mt-3">保存所有表单</button> </div> </div>
4. 完善后端API:支持批量插入
补全你的后端Controller,支持批量接收数据并插入数据库(假设用EF Core):
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Project1.Models; using Microsoft.EntityFrameworkCore; using System.Collections.Generic; using System.Threading.Tasks; namespace Project1.Controllers { [Route("api/AnimalAPI")] // 和前端服务的URL保持一致 [ApiController] public class AnimalAPIController : ControllerBase { private readonly YourDbContext _dbContext; // 替换成你的数据库上下文 public AnimalAPIController(YourDbContext dbContext) { _dbContext = dbContext; } [HttpPost] public async Task<IActionResult> PostOffspringList([FromBody] List<Offspring> offspringList) { if (offspringList == null || offspringList.Count == 0) { return BadRequest("没有要保存的数据"); } // 批量添加到数据库 await _dbContext.Offsprings.AddRangeAsync(offspringList); await _dbContext.SaveChangesAsync(); return Ok(offspringList); // 返回保存后的数据 } } }
如果前端和后端端口不同,别忘了在后端Program.cs配置跨域:
var builder = WebApplication.CreateBuilder(args); // 跨域配置 builder.Services.AddCors(options => { options.AddPolicy("AllowAll", policy => { policy.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); }); }); builder.Services.AddControllers(); builder.Services.AddDbContext<YourDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("YourConnectionString"))); var app = builder.Build(); app.UseHttpsRedirection(); app.UseCors("AllowAll"); // 启用跨域 app.UseAuthorization(); app.MapControllers(); app.Run();
做完这些调整后,你选择下拉数量、填写表单,点击保存按钮,就能把所有表单的数据批量提交到后端并插入数据库了。
内容来源于stack exchange
相关产品推荐
相关产品推荐

