Angular 表单设计,我应该使用多个表单还是使用一个表单更好?
Angular form design, should i use multiple forms or it's better to use a single form?
我要实现一个配置设置模式,UI看起来像附图
侧边栏上的多个标签,每个标签的内容将是右侧面板中的一个表格。
API 将在模式打开时获取所有设置配置。
没有API获取每个单独标签的数据,所有数据将在按下模态的'Save'按钮后保存。
API数据响应:
config: {
network: {...},
proxy: {...}
...
download: {...}
}
问题:
这个场景的数据管理应该怎么设计?
formValues.subscribe
在每个详细信息表单上,并将事件发送到父模态组件以同步数据?
- 我应该考虑使用 NgRx 吗?我真的没有这方面的经验。我应该使用 NgRx 是个好场景吗?
俗话说“千刀万剐”,这里同样适用。 Angular 给你工具,把架构留给你。
边栏上的多个选项卡意味着您可能会使用 master-detail 布局。
您可以使用多个表单,正如您已经注意到的那样,您必须同步它。
但是,我建议使用一种表单,它会覆盖整个细节布局,然后您将表单实例传递给细节组件。
所以想法是您将在父组件中有一个 FormGroup
,Save
按钮也是如此。你基本上用空 FormGroup
.
初始化它
form = fb.group({});
然后您将其作为 @Input
参数传递给详细视图组件,然后在 ngOnInit()
上添加 FormControl
@Input() form: FormGroup;
ngOnInit() {
this.form.addControl('enableLogging', new FormControl(this.settingsService.config.enableLogging));
// other form controls
}
settingsService.config
是您的 source-of-truth,即从您的 api 响应返回的配置。
单一表格会给您带来两个优势:
- 您不必费心同步每个表单的数据并进行整合。
- 因为你有一个保存按钮,它会保存所有数据,而不是在每个选项卡上保存,在父组件中有一个单一的表单,意味着你可以简单地 post 它与
this.form.value
点击保存按钮。
如果 是您的“parent” 创建整个表单的人
form=new FormGroup({
network:new FormGroup({
prop1:new FormControl(settingsService.network.prop1),
prop2:new FormControl(settingsService.network.prop2),
}),
proxy:new FormGroup({
prop1:new FormControl(settingsService.proxy.prop1),
prop2:new FormControl(settingsService.proxy.prop2),
})
...
})
您可以将 formGroup 传递给您的“children”
<form [formGroup]="form">
<config-component *ngIf="step==0" [group]="form.get('config')"></config-component>
<proxy-component *ngIf="step==1" [group]="form.get('proxi')"></proxi-component>
...
</form>
你children喜欢
@Input() group;
<form [formGroup]="group">
<input formControlName="prop1">
<input formControlName="prop2">
</form>
您不会丢失表单的值,因为它始终位于“parent”
更新。使用服务补充我的评论
假设您有一项服务
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class DataService {
data:any={}
constructor() { }
getData():Observable<any>{
...we get the data from a http or localStore or...
...and use pipe(tap) to store the value in "data"
e.g.
return of({}).pipe(tap((res)=>this.data=res));
}
saveData(){
..we use this.data to post to an http or to save in localStore...
}
}
我们的children就像
export class OneComponent implements OnInit {
form:FormGroup
constructor(private dataService:DataService){}
ngOnInit()
{
//see that create the form using the data from this.dataService.data.config
//in another component you'll use, e.g. this.dataService.data.netWork
const data=this.dataService.data.config|| {prop1:null,prop2:null}
this.form=new FormGroup(
{
prop1:new FormControl(data.prop1,Validators.required),
prop2:new FormControl(data.prop2)
})
}
saveData() //simple store in this.dataService.datadata.config the value of the form
//in another component you store, e.g. in this.dataService.datadata.netWork
{
this.dataService.data.config=this.form.value;
}
}
我们parent喜欢
<button (click)="navigate(0)">Config</button>
<button (click)="navigate(1)">NetWork</button>
<one-component #component *ngIf="page==0">
</one-component>
<two-component #component *ngIf="page==1">
</two-component>
看到“引用变量”,我们使用ViewChild获取组件
export class AppComponent implements OnInit {
@ViewChild('component') component:any;
constructor(public dataService:DataService){}
page=0;
ngOnInit()
{
this.dataService.getData().subscribe()
}
isValid(){
const form=this.component.form as FormGroup
if (form.valid)
this.component.saveData()
else
form.markAllAsTouched();
return form.valid
}
navigate(newIndex:number)
{
if (this.isValid())
this.page=newIndex
}
saveData()
{
if (this.isValid())
this.dataService.saveData()
}
}
中看到
我要实现一个配置设置模式,UI看起来像附图
侧边栏上的多个标签,每个标签的内容将是右侧面板中的一个表格。
API 将在模式打开时获取所有设置配置。
没有API获取每个单独标签的数据,所有数据将在按下模态的'Save'按钮后保存。
API数据响应:
config: {
network: {...},
proxy: {...}
...
download: {...}
}
问题:
这个场景的数据管理应该怎么设计?
formValues.subscribe
在每个详细信息表单上,并将事件发送到父模态组件以同步数据?- 我应该考虑使用 NgRx 吗?我真的没有这方面的经验。我应该使用 NgRx 是个好场景吗?
俗话说“千刀万剐”,这里同样适用。 Angular 给你工具,把架构留给你。
边栏上的多个选项卡意味着您可能会使用 master-detail 布局。
您可以使用多个表单,正如您已经注意到的那样,您必须同步它。
但是,我建议使用一种表单,它会覆盖整个细节布局,然后您将表单实例传递给细节组件。
所以想法是您将在父组件中有一个 FormGroup
,Save
按钮也是如此。你基本上用空 FormGroup
.
form = fb.group({});
然后您将其作为 @Input
参数传递给详细视图组件,然后在 ngOnInit()
上添加 FormControl
@Input() form: FormGroup;
ngOnInit() {
this.form.addControl('enableLogging', new FormControl(this.settingsService.config.enableLogging));
// other form controls
}
settingsService.config
是您的 source-of-truth,即从您的 api 响应返回的配置。
单一表格会给您带来两个优势:
- 您不必费心同步每个表单的数据并进行整合。
- 因为你有一个保存按钮,它会保存所有数据,而不是在每个选项卡上保存,在父组件中有一个单一的表单,意味着你可以简单地 post 它与
this.form.value
点击保存按钮。
如果 是您的“parent” 创建整个表单的人
form=new FormGroup({
network:new FormGroup({
prop1:new FormControl(settingsService.network.prop1),
prop2:new FormControl(settingsService.network.prop2),
}),
proxy:new FormGroup({
prop1:new FormControl(settingsService.proxy.prop1),
prop2:new FormControl(settingsService.proxy.prop2),
})
...
})
您可以将 formGroup 传递给您的“children”
<form [formGroup]="form">
<config-component *ngIf="step==0" [group]="form.get('config')"></config-component>
<proxy-component *ngIf="step==1" [group]="form.get('proxi')"></proxi-component>
...
</form>
你children喜欢
@Input() group;
<form [formGroup]="group">
<input formControlName="prop1">
<input formControlName="prop2">
</form>
您不会丢失表单的值,因为它始终位于“parent”
更新。使用服务补充我的评论
假设您有一项服务
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class DataService {
data:any={}
constructor() { }
getData():Observable<any>{
...we get the data from a http or localStore or...
...and use pipe(tap) to store the value in "data"
e.g.
return of({}).pipe(tap((res)=>this.data=res));
}
saveData(){
..we use this.data to post to an http or to save in localStore...
}
}
我们的children就像
export class OneComponent implements OnInit {
form:FormGroup
constructor(private dataService:DataService){}
ngOnInit()
{
//see that create the form using the data from this.dataService.data.config
//in another component you'll use, e.g. this.dataService.data.netWork
const data=this.dataService.data.config|| {prop1:null,prop2:null}
this.form=new FormGroup(
{
prop1:new FormControl(data.prop1,Validators.required),
prop2:new FormControl(data.prop2)
})
}
saveData() //simple store in this.dataService.datadata.config the value of the form
//in another component you store, e.g. in this.dataService.datadata.netWork
{
this.dataService.data.config=this.form.value;
}
}
我们parent喜欢
<button (click)="navigate(0)">Config</button>
<button (click)="navigate(1)">NetWork</button>
<one-component #component *ngIf="page==0">
</one-component>
<two-component #component *ngIf="page==1">
</two-component>
看到“引用变量”,我们使用ViewChild获取组件
export class AppComponent implements OnInit {
@ViewChild('component') component:any;
constructor(public dataService:DataService){}
page=0;
ngOnInit()
{
this.dataService.getData().subscribe()
}
isValid(){
const form=this.component.form as FormGroup
if (form.valid)
this.component.saveData()
else
form.markAllAsTouched();
return form.valid
}
navigate(newIndex:number)
{
if (this.isValid())
this.page=newIndex
}
saveData()
{
if (this.isValid())
this.dataService.saveData()
}
}
中看到