我有一个角度2的应用程序,在整个应用程序中大量使用表单。大多数表单是使用Angular中的反应形式模块构建的,但我正在使用的API也有很多动态字段"。
例如,"后端"允许用户为某些帖子/页面创建自定义字段,我也希望用户能够在我的Angular 2应用程序中使用它们。
示例
API为我提供了一个如下所示的JSON列表:
{
"id": "the-custom-field-id",
"label": "The input label",
"min": 4,
"max": 8,
"value": "The current value of the custom field"
},
...
现在,我在一个observable中获取自定义字段列表,并使用ngfor
循环它们并为每个条目生成表单元素,如下所示:
<div *ngFor="let cf of _customFields" class="form-group">
<label>{{cf.label}}</label>
<input id="custom-field-{{cf.id}}" type="text" class="form-control" value="{{cf.value}}">
</div>
然后在提交时,我进入DOM(使用jQuery)以使用&#34; ID&#34;来获取值。自定义字段。
这很丑陋,违背了不混合使用jQuery和Angular的想法。
必须有一种方法将这些动态表单集成到Angular中,所以我可以将它们与控制组和验证规则一起使用吗?
答案 0 :(得分:4)
是的,的确有。查看Angular 2's Dynamic Forms。它的基本要点是你创建类(问题),它定义了你想要访问的每种表单控件的选项。例如,作为最终结果,您可以拥有类似的内容:
<?php
if(count($_POST) > 0){ // if you have some value in AJAX request
if($_POST['Action'] == 'IMPLODEARRAY'){ // your condition
print_r($_POST['options']); // get all checkbox value.
}
}
?>
答案 1 :(得分:1)
要创建动态添加字段的表单,您需要在表单内使用FormArray,并在运行时添加自定义元素。以下是如何动态添加输入字段以允许用户通过单击“添加电子邮件:https://github.com/Farata/angular2typescript/blob/master/chapter7/form-samples/app/02_growable-items-form.ts
”按钮向表单输入多封电子邮件的示例答案 2 :(得分:-1)
另见我的例子。好评如此容易理解希望。 https://stackblitz.com/edit/angular-reactive-form-sobsoft
所以这就是我们在app.component.ts
中使用动态字段所需要的ngOnInit () {
// expan our form, create form array this._fb.array
this.exampleForm = this._fb.group({
companyName: ['', [Validators.required,
Validators.maxLength(25)]],
countryName: [''],
city: [''],
zipCode: [''],
street: [''],
units: this._fb.array([
this.getUnit()
])
});
}
/**
* Create form unit
*/
private getUnit() {
const numberPatern = '^[0-9.,]+$';
return this._fb.group({
unitName: ['', Validators.required],
qty: [1, [Validators.required, Validators.pattern(numberPatern)]],
unitPrice: ['', [Validators.required, Validators.pattern(numberPatern)]],
unitTotalPrice: [{value: '', disabled: true}]
});
}
/**
* Add new unit row into form
*/
private addUnit() {
const control = <FormArray>this.exampleForm.controls['units'];
control.push(this.getUnit());
}
/**
* Remove unit row from form on click delete button
*/
private removeUnit(i: number) {
const control = <FormArray>this.exampleForm.controls['units'];
control.removeAt(i);
}
现在使用HTML:
<!-- Page form start -->
<form [formGroup]="exampleForm" novalidate >
<div fxLayout="row" fxLayout.xs="column" fxLayoutWrap fxLayoutGap="3.5%" fxLayoutAlign="left" >
<!-- Comapny name input field -->
<mat-form-field class="example-full-width" fxFlex="75%">
<input matInput placeholder="Company name" formControlName="companyName" required>
<!-- input field hint -->
<mat-hint align="end">
Can contain only characters. Maximum {{exampleForm.controls.companyName.value.length}}/25
</mat-hint>
<!-- input field error -->
<mat-error *ngIf="exampleForm.controls.companyName.invalid">
This field is required and maximmum alowed charactes are 25
</mat-error>
</mat-form-field>
<!-- Country input field -->
<mat-form-field class="example-full-width" >
<input matInput placeholder="Country" formControlName="countryName">
<mat-hint align="end">Your IP country name loaded from freegeoip.net</mat-hint>
</mat-form-field>
</div>
<div fxLayout="row" fxLayout.xs="column" fxLayoutWrap fxLayoutGap="3.5%" fxLayoutAlign="center" layout-margin>
<!-- Street input field -->
<mat-form-field class="example-full-width">
<input matInput placeholder="Street" fxFlex="75%" formControlName="street">
</mat-form-field>
<!-- City input field -->
<mat-form-field class="example-full-width" >
<input matInput placeholder="City" formControlName="city">
<mat-hint align="end">City name loaded from freegeoip.net</mat-hint>
</mat-form-field>
<!-- Zip code input field -->
<mat-form-field class="example-full-width" fxFlex="20%">
<input matInput placeholder="Zip" formControlName="zipCode">
<mat-hint align="end">Zip loaded from freegeoip.net</mat-hint>
</mat-form-field>
</div>
<br>
<!-- Start form units array with first row must and dynamically add more -->
<mat-card formArrayName="units">
<mat-card-title>Units</mat-card-title>
<mat-divider></mat-divider>
<!-- loop throught units -->
<div *ngFor="let unit of exampleForm.controls.units.controls; let i=index">
<!-- row divider show for every nex row exclude if first row -->
<mat-divider *ngIf="exampleForm.controls.units.controls.length > 1 && i > 0" ></mat-divider><br>
<!-- group name in this case row index -->
<div [formGroupName]="i">
<div fxLayout="row" fxLayout.xs="column" fxLayoutWrap fxLayoutGap="3.5%" fxLayoutAlign="center">
<!-- unit name input field -->
<mat-form-field fxFlex="30%">
<input matInput placeholder="Unit name" formControlName="unitName" required>
</mat-form-field>
<!-- unit quantity input field -->
<mat-form-field fxFlex="10%">
<input matInput placeholder="Quantity" type="number" formControlName="qty" required>
</mat-form-field>
<!-- unit price input field -->
<mat-form-field fxFlex="20%">
<input matInput placeholder="Unit price" type="number" formControlName="unitPrice" required>
</mat-form-field>
<!-- unit total price input field, calculated and not editable -->
<mat-form-field >
<input matInput placeholder="Total sum" formControlName="unitTotalPrice">
</mat-form-field>
<!-- row delete button, hidden if there is just one row -->
<button mat-mini-fab color="warn"
*ngIf="exampleForm.controls.units.controls.length > 1" (click)="removeUnit(i)">
<mat-icon>delete forever</mat-icon>
</button>
</div>
</div>
</div>
<!-- New unit button -->
<mat-divider></mat-divider>
<mat-card-actions>
<button mat-raised-button (click)="addUnit()">
<mat-icon>add box</mat-icon>
Add new unit
</button>
</mat-card-actions>
</mat-card> <!-- End form units array -->
</form> <!-- Page form end -->