Angular 表单克隆不提交数据。但是父表单确实

Angular form clone does not submit data. But the parent form does

我正在开展一个 angular 项目,根据第一个表格中的债务人数量克隆 table。因此,假设第一个表格需要包含 3 个债务人,下一个表格将生成 3 个表格。但是,当您尝试从克隆的表单中保存数据时,它不起作用,但第一个表单仅在克隆的来源处有效。

  **MY TS FILE**
import { Component, OnInit } from "@angular/core";
import { FormGroup, FormBuilder, Validators } from "@angular/forms";
import { HttpClient } from "@angular/common/http";
import { Router } from "@angular/router";
import * as $ from 'jquery';


@Component({
selector: "app-annex",
templateUrl: "./annex.component.html",
styleUrls: ["./annex.component.css"],
})
export class AnnexComponent implements OnInit {
annexform: FormGroup;
id: any;
data = [];
decreaseDebtor: number;
alert: boolean = false;
alertUnsuccesful: boolean = false;
// annexForm: boolean = true;
// debtors_included: number;
myDebtors: any;
debtorsCount = 0;
// submitted = false;
// myDebtorsSubmit : number;
constructor(
 public fb: FormBuilder,
 private http: HttpClient,
 private router: Router
) {
 this.annexform = this.fb.group({
   debtor_name: ["", Validators.required],
   debtor_contact_person: ["", Validators.required],
   debtor_function: ["", Validators.required],
   debtor_address: ["", Validators.required],
   debtor_email: ["", [Validators.required, Validators.email]],
   debtor_phone_number: ["", Validators.required],
   debtor_proposed_limit: ["", Validators.required],
   debtor_invoice_term: ["", Validators.required],
   debtor_projected_turnover: ["", Validators.required],
   debtor_ledger: [null, Validators.required],
   client: Number,
 });
}
uploadLedgerFile(event: { target: HTMLInputElement }) {
 const file = (event.target as HTMLInputElement).files[0];
 this.annexform.patchValue({
   debtor_ledger: file,
 });
 this.annexform.get("debtor_ledger").updateValueAndValidity();
}

// convenience getter for easy access to form fields
get f() {
 return this.annexform.controls;
}

submitAnnexForm() {
 console.log(this.annexform.value)
 if (this.annexform.invalid) {
   return;
 }
 let formData: any = new FormData();
 formData.append("debtor_name", this.annexform.get("debtor_name").value);
 formData.append(
   "debtor_contact_person",
   this.annexform.get("debtor_contact_person").value
 );
 formData.append(
   "debtor_function",
   this.annexform.get("debtor_function").value
 );
 formData.append(
   "debtor_address",
   this.annexform.get("debtor_address").value
 );
 formData.append("debtor_email", this.annexform.get("debtor_email").value);
 formData.append(
   "debtor_phone_number",
   this.annexform.get("debtor_phone_number").value
 );
 formData.append("debtor_proposed_limit", this.annexform.get("debtor_proposed_limit").value);
 formData.append("debtor_invoice_term", this.annexform.get("debtor_invoice_term").value);
 formData.append("debtor_projected_turnover", this.annexform.get("debtor_projected_turnover").value);
 formData.append("debtor_ledger", this.annexform.get("debtor_ledger").value);
 formData.append("client", localStorage.getItem("id"));
 return this.http
   .post<{ id: string }>("http://127.0.0.1:8000/api/annex/", formData)
   .subscribe(
     (result) => {
       console.log(result); 
ngOnInit() {
 let retrievedObject = localStorage.getItem("id");
 console.log(retrievedObject);
 this.http
   .get<any>(`http://127.0.0.1:8000/api/create-client/${retrievedObject}/`)
   .subscribe(
     (res) => {
       this.decreaseDebtor = res.debtors_included;
       localStorage.setItem("debtors_included", res.debtors_included);
       this.myDebtors = JSON.parse(localStorage.getItem("debtors_included"));
       this.debtorsCount = JSON.parse(localStorage.getItem("debtors_count"));
       console.log(this.decreaseDebtor);
       console.log(this.myDebtors);
     },
     (error) => console.log(error)
   );
 $(document).ready(function () {
   let debtors = JSON.parse(localStorage.getItem("debtors_included"));
   let e = $(".rowToClone");
   for (let i = 0; i <= debtors-2; i++) {
     e.clone().insertAfter(e)
   }
 $(document).find(".rowToClone").trigger("create")
 });
}
}
  

这是我的 HTML 文件

      <div id="myDiv">
        <form class="rowToClone table-form" name="annexForm" [formGroup]="annexform" (ngSubmit)="submitAnnexForm($event)" onsubmit="event.preventDefault()" >
          <table class="table">
            <!--Table body-->
            <tbody class="annex-body">
              <tr>
                <td class="table-input-data">
                  <input
                    class="my-input"
                    type="text"
                    formControlName="debtor_name"
                    required
                    id="debtor_name"
                  />
                </td>
                <td class="table-input-data">
                  <input
                    class="my-input"
                    type="text"
                    formControlName="debtor_contact_person"
                    required
                    id="debtor_contact_person"
                  />
                </td>
                <td class="table-input-data">
                  <input
                    class="my-input"
                    type="text"
                    class="table-head-data3"
                    formControlName="debtor_function"
                    required
                    id="debtor_function"
                  />
                </td>
                <td class="table-input-data">
                  <input
                    class="my-input"
                    type="text"
                    formControlName="debtor_address"
                    required
                    id="debtor_address"
                  />
                </td>
                <td class="table-input-data">
                  <input
                    class="my-input"
                    type="email"
                    formControlName="debtor_email"
                    required
                    id="debtor_email"
                  />
                </td>
                <td class="table-input-data">
                  <input
                    class="my-input"
                    type="text"
                    formControlName="debtor_phone_number"
                    required
                    id="debtor_phone_number"
                  />
                </td>
                <td class="table-input-data">
                  <input
                    class="my-input"
                    type="text"
                    formControlName="debtor_proposed_limit"
                    required
                    id="debtor_proposed_limit"
                  />
                </td>
                <td class="table-input-data">
                  <input
                    class="my-input"
                    type="text"
                    formControlName="debtor_invoice_term"
                    required
                    id="debtor_invoice_term"
                  />
                </td>
                <td class="table-input-data">
                  <input
                    class="my-input"
                    type="text"
                    formControlName="debtor_projected_turnover"
                    required
                    id="debtor_projected_turnover"
                  />
                </td>
                <td class="table-input-data">
                  <input
                    class="my-input"
                    id="debtor_ledger"
                    type="file"
                    (change)="uploadLedgerFile($event)"
                    required
                  />
                </td>
                <td class="table-input-data">
                  <button
                    class="my-input"
                    class="mybutton"
                    id="submit"
                    type="submit"
                  >
                    Save
                  </button>
                </td>
              </tr>
            </tbody>
            <!--Table body-->
          </table>
        </form>
      </div>

我在这里看到了很多问题。

  • 您在订阅 POST 数据的 http 请求中调用了您的 ngInit 回调方法。那要么是复制和过去的错误,要么您确实需要将其从该订阅中移出。
  • 作为一般规则,angular 不建议直接操作 DOM,因为您的代码正在执行。

据我所知,

  • 您正在操纵 DOM 以便能够拥有响应使用事件的动态表单
  • 那么您正在尝试访问 class
  • 中的这些克隆元素

您的克隆表单在 class 中永远不可用的原因是您直接操作 DOM 而不是在 class 中创建对象。

即克隆表单 DOM 元素将无法在 class.

中使用

如果您还没有完成 angular.io 上的 dynamic form walkthrough,您可能会受益。

我建议嵌套 FormGroups 或使用 FormArray。以 nestedFormGroups 为例,你可以按照

的方式做一些事情
constructor(
 public fb: FormBuilder,
 private http: HttpClient,
 private router: Router
) {
  this.annexForm = this.fb.group( {
     vendor1: this.fb.group(this.getVendorFormFields() ),
     vendor1: this.fb.group(this.getVendorFormFields() )
  });
}

getVendorFormFields() {
  return {
    debtor_name: ["", Validators.required],
    debtor_contact_person: ["", Validators.required],
    debtor_function: ["", Validators.required],
    debtor_address: ["", Validators.required],
    debtor_email: ["", [Validators.required, Validators.email]],
    debtor_phone_number: ["", Validators.required],
    debtor_proposed_limit: ["", Validators.required],
    debtor_invoice_term: ["", Validators.required],
    debtor_projected_turnover: ["", Validators.required],
    debtor_ledger: [null, Validators.required],
    client: Number,
  };
}

这允许您为每个供应商保留特定的 formGroups,并允许您在 HTML 模板中隔离验证(如果这是您需要的)。

另一种可能使事情更易于管理的方法是创建一个 VendorForm 组件。在此组件中,具有您需要的表单和任何验证。这将允许您将 get/sets 数据的逻辑与表单分开。这种类型的分离使您的代码管理变得更加容易,并且可以让您更轻松地管理 add/remove 供应商并为每个供应商提供相同的表单输入控件。

另外,您可以通过在表单上使用 form.getRawValue() 来节省一些代码。这将有效地完成与所有 .appendData 方法相同的事情。它采用一种形式 returns 一个包含 name/value 对的 JSON 对象。然后您可以将其传递到您的 HTTP 请求中。

我认为这里的简短版本是你正在尝试做一些事情 'work around' angular 以获得你想要的东西。我建议遵循 angular 提供的动态表单示例。没有任何理由像您目前所做的那样操纵 DOM。

希望这对您有所帮助。祝你好运