以 Angular 反应形式显示多个送货地址
Displaying multiple shipping addresses in Angular reactive Form
我正在尝试显示来自 API 的送货地址,目前数据库中有三个地址,但只有一个地址显示了 3 次
这是组件Html代码
<div class="row" formControlName="shippingAddressForm">
<div class="form-group col-6">
<h1 class="h3 mt-4">Shipping Address</h1>
<div *ngFor="let item of shippingAddress?.data">
<form
[formGroup]='shippingAddressForm'
(ngSubmit)="Save(shippingAddressForm.value)"
>
<br>
<app-text-input formControlName="country" [label]='"Country"'></app-text-input>
<app-text-input [formControl]='shippingAddressForm.controls["phone"]' [label]='"Phone Number"'></app-text-input>
<app-text-input formControlName="name" [label]='"Name"'></app-text-input>
<app-text-input [formControl]='shippingAddressForm.controls["email"]' [label]='"Email"'></app-text-input>
<app-text-input [formControl]='shippingAddressForm.controls["address"]' [label]='"Address"'></app-text-input>
<div class="row">
<div class="col-sm-4">
<label for="state">State</label>
</div>
<select class="custom-select form-group"
style="width: auto"
formControlName="state"
[class.is-invalid]='shippingAddressForm.get("state").errors
&& shippingAddressForm.get("state").touched'
>
<option *ngFor='let state of selectedState?.data.data' [value]="state.id"> {{state.state}}</option>
</select>
</div>
<div class="row">
<div class="col-sm-4">
<label for="city">City</label>
</div>
<select class="custom-select form-group"
style="width: auto"
formControlName="city"
[class.is-invalid]='shippingAddressForm.get("city").errors
&& shippingAddressForm.get("city").touched'
>
<option *ngFor='let city of selectedCity?.data.data' [value]="city"> {{city}}</option>
</select>
</div>
</form>
</div>
</div>
</div>
这是TS组件代码
loadShippingAddress() {
this.shippingaddressService.getShippingAddress().subscribe(address => {
console.log('address data',address);
this.shippingAddress = address;
if(this.shippingAddress) {
console.log('if address',address);
for (let item of this.shippingAddress.data)
this.shippingAddressForm.patchValue(item);
}
}, error => {
console.log(error);
})
} 这是控制台日志中的数据,显示数据库中的所有送货地址
这是申请中的结果
here i am considering that your form has only following fields
country,phone
此处在 init 中刚刚声明了表单结构,并在 loadShippingAddress() 中添加了创建表单的实际逻辑
yourForm : FormGroup;
ngOnInit()
{
this.yourForm = new FormGoup({
‘addressess’: new FormArray([])
})
}
loadShippingAddress() {
let addressess = new FormArray([]);
this.shippingaddressService.getShippingAddress().subscribe(address =>
{
this.shippingAddress = address;
if(this.shippingAddress)
{
for(let address of this.shippingAddress.data)
{
addressess.push(
new FormGroup({
'country':new FormControl(address.country),
'phone':new FormControl(address.phone)
})
)
}
}
this.yourForm = new FormGoup({
'addressess' : addressess
})
}, error =>
{
console.log(error);
})
}
//getter used in html to loop through address
get adddressControls(){
return (<FormArray>this.yourForm.get('addressess')).controls
}
html
<form [formGroup]='yourForm'>
<div class="row">
<div class="col-xs-12" formArrayName="addressess">
<div
style="margin:5px;"
class="row"
*ngFor="let address of adddressControls;let i = index"
[formGroupName]="i"
>
<div class="col-xs-8">
<app-text-input formControlName="country" [label]='"Country"'></app-text-input>
</div>
<div class="col-xs-2">
<app-text-input formControlName="phone" [label]='"Phone Number"'></app-text-input>
</div>
</div>
<hr>
</div>
</div>
</form>
注意:这是另一种使用表单而不是 formArray 的方法。这只是一次“练习”。我个人更喜欢使用 FormArray。
假设您有一项服务 return 一组“船舶”
[{
prop1:"prop1",
prop2:"prop2"
},
{
prop1:"another1",
prop2:"another2"
}]
你有一个组件
<form [formGroup]="form">
<input formControlName="prop1">
<input formControlName="prop2">
</form>
您使用 @Input
和 setter 创建表单
form:FormGroup;
@Input() set data(value){
this.form=new FormGroup({
prop1:new FormControl(value.prop1),
prop2:new FormControl(value.prop2)
})
}
你的父组件可以像
<div *ngFor="let ship of ships">
<ship [data]="ship"></ship>
</div>
<button (click)="submit()">submit</button>
要获取“飞船”的值,我们可以使用 ViewChildren 并在 ngOnInit 中从服务获取数据
@ViewChildren(ShipComponent) forms:QueryList<ShipComponent>
constructor(private dataService:DataService){}
ships:any[]
result:any[]
ngOnInit(){
this.dataService.getData().subscribe(res=>{
this.ships=res
})
}
submit(){
this.result=this.forms.map(x=>x.form.value)
}
如果我们想从父级添加“新船”,我们创建一个函数
add(){
this.ships=[...this.forms.map(x=>x.form.value),
{prop1:null,prop2:null}]
}
如果我们想删除“ships”有点复杂,我们需要传递ship的“index”并使用输出方式
在 ship 组件中,添加一个 Input index 和 output remove
@Input() index;
@Output() remove:EventEmitter<number>=new EventEmitter<number>()
并在.html
<button (click)="remove.emit(index)">remove</button>
在父级中我们更改 .html
<div *ngFor="let ship of ships;let i=index">
<ship [data]="ship" [index]="i" (remove)="remove($event)"></ship>
</div>
并添加一个函数删除
remove(index:number)
{
this.ships.splice(index,1)
}
我正在尝试显示来自 API 的送货地址,目前数据库中有三个地址,但只有一个地址显示了 3 次
这是组件Html代码
<div class="row" formControlName="shippingAddressForm">
<div class="form-group col-6">
<h1 class="h3 mt-4">Shipping Address</h1>
<div *ngFor="let item of shippingAddress?.data">
<form
[formGroup]='shippingAddressForm'
(ngSubmit)="Save(shippingAddressForm.value)"
>
<br>
<app-text-input formControlName="country" [label]='"Country"'></app-text-input>
<app-text-input [formControl]='shippingAddressForm.controls["phone"]' [label]='"Phone Number"'></app-text-input>
<app-text-input formControlName="name" [label]='"Name"'></app-text-input>
<app-text-input [formControl]='shippingAddressForm.controls["email"]' [label]='"Email"'></app-text-input>
<app-text-input [formControl]='shippingAddressForm.controls["address"]' [label]='"Address"'></app-text-input>
<div class="row">
<div class="col-sm-4">
<label for="state">State</label>
</div>
<select class="custom-select form-group"
style="width: auto"
formControlName="state"
[class.is-invalid]='shippingAddressForm.get("state").errors
&& shippingAddressForm.get("state").touched'
>
<option *ngFor='let state of selectedState?.data.data' [value]="state.id"> {{state.state}}</option>
</select>
</div>
<div class="row">
<div class="col-sm-4">
<label for="city">City</label>
</div>
<select class="custom-select form-group"
style="width: auto"
formControlName="city"
[class.is-invalid]='shippingAddressForm.get("city").errors
&& shippingAddressForm.get("city").touched'
>
<option *ngFor='let city of selectedCity?.data.data' [value]="city"> {{city}}</option>
</select>
</div>
</form>
</div>
</div>
</div>
这是TS组件代码
loadShippingAddress() {
this.shippingaddressService.getShippingAddress().subscribe(address => {
console.log('address data',address);
this.shippingAddress = address;
if(this.shippingAddress) {
console.log('if address',address);
for (let item of this.shippingAddress.data)
this.shippingAddressForm.patchValue(item);
}
}, error => {
console.log(error);
})
} 这是控制台日志中的数据,显示数据库中的所有送货地址
这是申请中的结果
here i am considering that your form has only following fields country,phone
此处在 init 中刚刚声明了表单结构,并在 loadShippingAddress() 中添加了创建表单的实际逻辑
yourForm : FormGroup;
ngOnInit()
{
this.yourForm = new FormGoup({
‘addressess’: new FormArray([])
})
}
loadShippingAddress() {
let addressess = new FormArray([]);
this.shippingaddressService.getShippingAddress().subscribe(address =>
{
this.shippingAddress = address;
if(this.shippingAddress)
{
for(let address of this.shippingAddress.data)
{
addressess.push(
new FormGroup({
'country':new FormControl(address.country),
'phone':new FormControl(address.phone)
})
)
}
}
this.yourForm = new FormGoup({
'addressess' : addressess
})
}, error =>
{
console.log(error);
})
}
//getter used in html to loop through address
get adddressControls(){
return (<FormArray>this.yourForm.get('addressess')).controls
}
html
<form [formGroup]='yourForm'>
<div class="row">
<div class="col-xs-12" formArrayName="addressess">
<div
style="margin:5px;"
class="row"
*ngFor="let address of adddressControls;let i = index"
[formGroupName]="i"
>
<div class="col-xs-8">
<app-text-input formControlName="country" [label]='"Country"'></app-text-input>
</div>
<div class="col-xs-2">
<app-text-input formControlName="phone" [label]='"Phone Number"'></app-text-input>
</div>
</div>
<hr>
</div>
</div>
</form>
注意:这是另一种使用表单而不是 formArray 的方法。这只是一次“练习”。我个人更喜欢使用 FormArray。
假设您有一项服务 return 一组“船舶”
[{
prop1:"prop1",
prop2:"prop2"
},
{
prop1:"another1",
prop2:"another2"
}]
你有一个组件
<form [formGroup]="form">
<input formControlName="prop1">
<input formControlName="prop2">
</form>
您使用 @Input
和 setter 创建表单
form:FormGroup;
@Input() set data(value){
this.form=new FormGroup({
prop1:new FormControl(value.prop1),
prop2:new FormControl(value.prop2)
})
}
你的父组件可以像
<div *ngFor="let ship of ships">
<ship [data]="ship"></ship>
</div>
<button (click)="submit()">submit</button>
要获取“飞船”的值,我们可以使用 ViewChildren 并在 ngOnInit 中从服务获取数据
@ViewChildren(ShipComponent) forms:QueryList<ShipComponent>
constructor(private dataService:DataService){}
ships:any[]
result:any[]
ngOnInit(){
this.dataService.getData().subscribe(res=>{
this.ships=res
})
}
submit(){
this.result=this.forms.map(x=>x.form.value)
}
如果我们想从父级添加“新船”,我们创建一个函数
add(){
this.ships=[...this.forms.map(x=>x.form.value),
{prop1:null,prop2:null}]
}
如果我们想删除“ships”有点复杂,我们需要传递ship的“index”并使用输出方式
在 ship 组件中,添加一个 Input index 和 output remove
@Input() index;
@Output() remove:EventEmitter<number>=new EventEmitter<number>()
并在.html
<button (click)="remove.emit(index)">remove</button>
在父级中我们更改 .html
<div *ngFor="let ship of ships;let i=index">
<ship [data]="ship" [index]="i" (remove)="remove($event)"></ship>
</div>
并添加一个函数删除
remove(index:number)
{
this.ships.splice(index,1)
}