当字段未触及时,Angular 反应形式返回空值 [英] Angular reactive form returns empty values when fields are untouched

查看:20
本文介绍了当字段未触及时,Angular 反应形式返回空值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的用例中,当用户单击编辑按钮时,Angular 对后端进行 HTTP 调用并检索对象,然后在 EDIT 表单上填充这些值.用户可以更新或保持字段不变.当点击 update 按钮时,Angular 应该获取表单中存在的所有这些值并将它们发送到后端.所以,这是问题所在,在将值加载到编辑页面表单并更新某些字段并保留某些字段不变后,未修改的值会变为空.这真的很奇怪

product-edit.component.html

<h2>更新产品</h2><br/><form [formGroup]="productForm"><div class="form-group"><label for="id">产品 ID</label><input class="form-control" formControlName="id" id="id" type="text" value="{{product.id}}"><small class="form-text text-muted" id="emailHelp"></small>

<div class="form-group"><label for="name">Name</label><input class="form-control" formControlName="name" id="name" type="text" value="{{product.name}}">

<div class="form-group"><label for="description">Description</label><input class="form-control" formControlName="description" height="100" id="description" required type="text"[value]="product.description" width="200">

<div class="form-group"><label for="currency">价格</label><br/><标签><select (load)="loadCurrencies()" class="form-control" [value]="product.price.currency.symbol" formControlName="currency" id="currency" name="currency"><option *ngFor="让货币的货币" value={{currency.id}}>{{货币名称}}</选项></选择><input formControlName="price" id="price" required style="margin: 10px; padding: 5px" type="text" [value]="product.price.amount">

<div class="form-group"><标签>类别:<select (load)="loadCategories()" class="form-control" formControlName="category" name="category"><option [value]="category.id" *ngFor="let category of category">{{分类名称}}</选项></选择>

<div class="form-group"><标签>制造商:<select (load)="loadManufacturers()" class="form-control" [value]="product.manufacturer.name" formControlName="manufacturer" name="manufacturer"><option [value]="manufacturer.id" *ngFor="让制造商的制造商" >{{生产商名称}}</选项></选择>

<button (click)="updateProduct()" class="btn btn-primary" type="submit">Submit</button><button (click)="goBack()" class="btn btn-primary" style="margin-left: 30px" type="button">取消</button></表单>

ProductEditComponent

import {Component, OnInit} from '@angular/core';从'../model/product'导入{产品};从'../service/product.service'导入{ProductService};从@angular/router"导入 {ActivatedRoute, Router};从../../../app.constants"导入 {CATEGORY_API_URL, CURRENCY_API_URL, MANUFACTURER_API_URL, PRODUCT_API_URL, SERVER_URL};从@angular/forms"导入 {FormControl、FormGroup、Validators};从 '../model/price' 导入 {Price};从'../model/currency'导入{Currency};从../../category/model/category"导入{类别};从'../model/manufacturer'导入{制造商};从'../../category/service/category.service'导入{CategoryService};@成分( {选择器:'app-product-edit',templateUrl: './product-edit.component.html',styleUrls: ['./product-edit.component.css']})导出类 ProductEditComponent 实现 OnInit{产品:产品;类别:数组<类别>;货币:数组<货币>;制造商:Array<制造商>;产品表格=新表格组({id: new FormControl( {value: '', disabled: true}, Validators.minLength( 2 ) ),名称:new FormControl( '' ),描述:new FormControl( '' ),价格:新的FormControl(''),类别:new FormControl( '' ),货币:new FormControl(''),制造商: new FormControl( '' )});构造函数(私有产品服务:产品服务,私有类别服务:类别服务,私人路线:ActivatedRoute,专用路由器:路由器){}ngOnInit(){this.getProduct();this.loadCategories();this.loadCurrencies();this.loadManufacturers();}productDataAvailable(): 布尔值{返回 this.product!==undefined;}回去(){this.router.navigate( ['/product'] );}私有 getProduct(){const id=this.route.snapshot.paramMap.get('id');const url=SERVER_URL+PRODUCT_API_URL+'find/'+id;this.productService.getProductDetails( url ).pipe().订阅(数据 =>{this.product=数据;},错误 =>{控制台日志(错误);},() =>console.log('getProduct() 成功'));}私人更新产品(){const id=this.route.snapshot.paramMap.get('id');const url=SERVER_URL+PRODUCT_API_URL+'更新';const product=new Product();product.id=Number( id );product.name=this.productForm.get('name').value;product.description=this.productForm.get('description').value;const currency=new Currency( this.productForm.get( 'currency' ).value, 'USD', '$' );product.price=new Price(currency , this.productForm.get( 'price' ).value );product.category=new Category( this.productForm.get( 'category' ).value );product.manufacturer=new Manufacturer( this.productForm.get( 'manufacturer' ).value );product.lastModifiedBy='管理员';product.lastModifiedDate='管理员';this.productService.updateProduct( url, product ).subscribe(值 =>{console.log('产品更新成功');}, error1 =>{console.log('更新产品失败');},() =>{this.router.navigate( ['/product/list'] );});}私人 loadCategories(){const url=SERVER_URL+CATEGORY_API_URL+'list';this.categoryService.getCategories( url ).subscribe(类别 =>{//@ts-忽略this.categories=categories;console.log( '成功加载类别' );},错误 1 ​​=>{console.log('加载分类失败');},() =>{});}私人 loadCurrencies(){const url=SERVER_URL+CURRENCY_API_URL+'list';this.productService.getCurrencies( url ).subscribe(货币 =>{this.currencies=货币;},错误 1 ​​=>{console.log('加载货币失败');},() =>{});}私有负载制造商(){const url=SERVER_URL+MANUFACTURER_API_URL+'list';this.productService.getManufacturers( url ).subscribe(制造商 =>{this.manufacturers=制造商;console.log('成功加载制造商');},错误 1 ​​=>{console.log('加载制造商失败');},() =>{});}}

Angular 版本

Angular CLI:7.3.8节点:10.15.0操作系统:达尔文 x64角度:7.2.12... 动画、通用、编译器、编译器-cli、核心、表单... http、语言服务、平台浏览器... 平台浏览器动态,路由器套餐版本-----------------------------------------------------------@angular-devkit/架构师 0.13.8@angular-devkit/build-angular 0.13.8@angular-devkit/build-optimizer 0.13.8@angular-devkit/build-webpack 0.13.8@angular-devkit/核心 7.3.8@angular-devkit/schematics 7.3.8@angular/cli 7.3.8@ngtools/webpack 7.3.8@原理图/角度 7.3.8@原理图/更新 0.13.8rxjs 6.4.0打字稿 3.2.4网络包 4.29.0

解决方案

据我所知,您已经发出 HTTP 请求以从您的服务器获取数据,但您没有填充您的 productForm FormGroup 正确的方式.由于您使用的是响应式表单,我强烈建议您使用 patchValuesetValue 以更新您的 FormControls.

对于您的情况,我会推荐 patchValue,因为它比 setValue 更灵活.patchValue 不需要在参数中指定所有 FormControl 以更新/设置表单控件的值.

这是如何使用 patchValue 的.在您的 getProduct() 方法中,您可以通过执行此操作将 getProductDetails()data 响应中的属性传递到您的 FormGroup 中;

getProduct() {const id = this.route.snapshot.paramMap.get('id');const url = SERVER_URL + PRODUCT_API_URL + 'find/' + id;this.productService.getProductDetails(url).pipe().订阅(数据 =>{this.productForm.patchValue({id:数据.id名称:data.name描述:data.description//其他表单域})},错误 =>{控制台日志(错误);},() =>console.log('getProduct() 成功'));}

此外,在您的模板 html 上,无需在每个

发送“验证码”获取 | 15天全站免登陆