I am going to implement a modal of configuration settings, the UI looks like the attached image
Multiple tabs on the sidebar, the content of each tab will be a form in the right panel.
API will fetch all the settings config once when the modal is open.
There's no API for fetching data of each individual tab, and all data will be saved after pressing the 'Save' button of the modal.
API data response:
config: {
network: {...},
proxy: {...}
...
download: {...}
}
Question:
How should I design the data management of this scenario?
formValues.subscribe
on each detail form, and emit the event to parent modal component for syncing data?if is your "parent" who create the whole form
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),
})
...
})
You can pass the formGroup to your "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>
Your childrens like
@Input() group;
<form [formGroup]="group">
<input formControlName="prop1">
<input formControlName="prop2">
</form>
You don't loose the values of the form because you has it always in "parent"
Update. Complementary my comments using a service
Imagine you has a service
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...
}
}
Ours children are like
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;
}
}
Our parent like
<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>
See the "reference variable", we use ViewChild to get the component
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()
}
}
You can see in an ugly stackblitz