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。
希望这对您有所帮助。祝你好运
我正在开展一个 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。
希望这对您有所帮助。祝你好运