首页 > 解决方案 > 如何将反应式表单与模型连接起来,以便将数据发送到数据库

问题描述

我有一个应用程序(生成 jhipster 的前端角度后端 Java Spring boot)。还有一种反应形式,我可以节省材料,例如螺丝之类的东西。但我似乎无法将它与我的材料模型类正确连接我只能保存一个属性,那就是数量。我试图用 [(ngModel)] 解决它,这是我尝试过的,但它只适用于数量。卖家名称和价格金额也可以正常工作。我不明白为什么一个属性有效而其他属性无效,我似乎找不到错误。

<div class="input-group input-group-sm col-12 col-md-6 mb-4">
            <div class="input-group-prepend">
              <span class="input-group-text" id="materialName">Name</span>
            </div>
            <input type="text" class="form-control" aria-label="Sizing example input"
                   aria-describedby="inputGroup-sizing-sm"
                   formControlName="name"
                   [(ngModel)]="materialModel.name" name="name">
          </div>
          <div class="input-group input-group-sm col-12 col-md-6 mb-4">
            <div class="input-group-prepend">
              <span class="input-group-text" id="materialCode">Material No</span>
            </div>
            <input type="text" class="form-control" aria-label="Sizing example input"
                   aria-describedby="inputGroup-sizing-sm"
                   formControlName="articleNumber"
                   name="articleNumber"
                   [(ngModel)]="materialModel.articleNumber">
          </div>
        </div>
        <div class="form-row mb-4">
          <div class="input-group input-group-sm col-12 col-md-6 mb-4">
            <div class="input-group-prepend">
              <span class="input-group-text" id="quantity">Quantity</span>
            </div>
            <input type="text" class="form-control" aria-label="Sizing example input"
                   formControlName="quantity"
                   [(ngModel)]="materialModel.quantity" name="quantity"
                   aria-describedby="inputGroup-sizing-sm">
          </div>
          <div class="divider"></div>
          <div class="-pull-right">
            <button type="button" class="btn btn-primary mb-2" (click)="addSellerInput()">Add Seller</button>
          </div>
          <div class="form-row mb-4" formArrayName="buyInformation"
               *ngFor="let buyInformation of buyInformation().controls; let i = index">
            <div class="input-group input-group-sm col-12 col-md-6 mb-4" [formGroupName]="i">
              <div class="input-group-prepend">
                <span class="input-group-text" id="sellerName">Seller Name</span>
              </div>
              <input type="text" class="form-control" aria-label="Sizing example input"
                     aria-describedby="inputGroup-sizing-sm"
                     formControlName="seller"
                     [(ngModel)]="sellerModel.name">
            </div>
            <div class="input-group input-group-sm col-12 col-md-6 mb-4" [formGroupName]="i">
              <div class="input-group-prepend">
                <span class="input-group-text" id="materialUnitPrice">Price</span>
              </div>
              <input type="text" class="form-control" aria-label="Sizing example input"
                     aria-describedby="inputGroup-sizing-sm"
                     formControlName="price"
                     name="price"
                     [(ngModel)]="priceModel.amount">
            </div>
          </div>

这是我的 ts 文件:

materialAddForm: FormGroup;
  formData: any;
  @Input()
  materialModel: MaterialModel
  @Input()
  priceModel: PriceModel
  @Input()
  sellerModel: SellerModel

  constructor(
    private materialService: MaterialService,
    private priceService: PriceService,
    private sellerService: SellerService,
    private fb: FormBuilder
  ) {
    this.materialModel = new MaterialModel()
    this.priceModel = new PriceModel()
    this.sellerModel = new SellerModel()

  }


  ngOnInit() {
    this.materialAddForm = this.fb.group({
      name: new FormControl(''),
      articleNumber: new FormControl(''),
      materialType: new FormControl(''),
      quantity: new FormControl(''),
      buyInformation: this.fb.array([])
    })
  }


  buyInformation(): FormArray {
    return this.materialAddForm.get("buyInformation") as FormArray
  }

  saveMaterial() {
    this.sellerService.addSeller(this.sellerModel).subscribe(console.log);
    this.priceService.addPrice(this.priceModel).subscribe(console.log);
    this.materialService.addMaterial(this.materialModel).subscribe(console.log);
    this.materialAddForm.reset()
    this.buyInformation().clear()


    console.log(this.materialModel)

  }

  newBuyForm() {
    return this.fb.group(({
      seller: new FormControl(''),
      price: new FormControl(''),
    }));
  }

  addSellerInput() {
    this.buyInformation().push(this.newBuyForm())

  }

我的材料模型:

export class MaterialModel{
  constructor(
    public id?: number,
    public name?: string,
    public articleNumber?: number,
    public quantity?: number,
    public price?: number,
    public imageURL?: string,
    public materialType?: string
     ) {}


}

到目前为止,只有数量在材料中起作用。

标签: angulartypescriptspring-bootjhipster

解决方案


你的代码确实有一些错误

1.-使用接口与类

如果您仅将类用于已定义的属性,则最好使用接口。

export interface MaterialModel{
    public id?: number;
    public name?: string;
    public articleNumber?: number;
    public quantity?: number;
    public price?: number;
    public imageURL?: string;
    public materialType?: string;
}

2.-创建FormGroup有两种方式,使用构造函数(formGroup的每个属性是新的FormControl或新的FormGroup或新的FormArray)

this.form=new FormGroup({
      name: new FormControl(''),
      articleNumber: new FormControl(''),
      materialType: new FormControl(''),
      ...
      buyInformation: new FormArray([])
})

使用 FormBuilder(请参阅在这种情况下不要使用新的 FormControl)

this.form=this.fb.group({
      name: [''],
      articleNumber: [''],
      materialType: [''],
      ...
      buyInformation: this.fb.array([])
})

3.-当您使用httpClient发帖时,您将JSON对象作为“数据”的参数传递,您可以直接使用this.form.value(或使用form.value的值创建一个“ad hoc”对象)

//if the properties of the form is the same you need, you can do
    this.sellerService.addSeller(this.materialAddForm.value)
          .subscribe((res:any)=>{console.log(res)});

//or 
    this.sellerService.addSeller({
           materialName:this.materialAddForm.value.name
           material_code:this.materialAddForm.value.articleNumber
           ...
          })
          .subscribe((res:any)=>{console.log(res)});

4.- 不要在同一个标​​签中混合 [(ngModel)] 和 formControlName。

5.- 通常(但实际上它是可选的)通常我们使用“getter”来获取 formArray

   get buyInformation(): FormArray {
    return this.materialAddForm.get("buyInformation") as FormArray
  }

用作,例如

<!--see that we remove the ()-->
<div *ngFor="let buyInformation of buyInformation.controls;.." >

6.- 取出循环的“formArrayName”,好吧,工作,但它是一些cofussed

<div formArrayName="buyInformation">
    <div *ngFor="let buyInformation of buyInformation.controls;let i=index"
        [formGroupName]="i">
         <input formControlName="seller">
    </div>
</div>

7.- 如果您使用 a@Input来传递数据,请使用此输入来创建表单。为此,我喜欢有一个返回 FormGroup 的函数

getFormGroup(data:any=null)
{
   data=data || {} as MaterialModel
   return new FormControl({
      name: new FormControl(''),
      articleNumber: new FormControl(''),
      materialType: new FormControl(''),
      quantity: new FormControl(''),
      buyInformation: data.byInfomation?new FormArray(data.buyInformation.map(x=>this.newBuyForm(x)):
         new FormArray([])
    })
}
//and 
newBuyForm(data:any=null)
{
   data=data || { seller:'',price:0}
   return new FormGroup(({
      seller: new FormControl(data.seller),
      price: new FormControl(data.price),
    }));
}

所以,在输入中,看到如果你不再使用materialModel,你只能使用FromGroup

@Input() set materialModel(value){
    this.materialAddForm=this.getFormGroup(value)
}

推荐阅读