Je vais implémenter un modal de paramètres de configuration, l'interface utilisateur ressemble à l'image ci-jointe entrez la description de l'image ici

Plusieurs onglets sur la barre latérale, le contenu de chaque onglet sera un formulaire dans le panneau de droite.

L'API récupérera tous les paramètres de configuration une fois lorsque le modal est ouvert.

Il n'y a pas d'API pour récupérer les données de chaque onglet individuel, et toutes les données seront enregistrées après avoir appuyé sur le bouton `` Enregistrer '' du modal.

Réponse des données API:

config: {
    network: {...},
    proxy: {...}
    ...
    download: {...}
}

Question:

Comment dois-je concevoir la gestion des données de ce scénario?

  • formValues.subscribe sur chaque formulaire détaillé et émettre l'événement vers le composant modal parent pour la synchronisation des données?
  • Dois-je envisager d'utiliser NgRx? Je n'ai pas vraiment d'expérience avec ça. Est-ce un bon scénario que je devrais utiliser NgRx?
0
huan feng 30 août 2020 à 06:51

2 réponses

Meilleure réponse

Si est votre "parent" qui crée le formulaire entier

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),
   })
   ...
})

Vous pouvez transmettre le formGroup à vos "enfants"

<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>

Vos enfants aiment

@Input() group;

<form [formGroup]="group">
   <input formControlName="prop1">
   <input formControlName="prop2">
</form>

Vous ne perdez pas les valeurs du formulaire car vous l'avez toujours dans "parent"

Mettre à jour . Complémentaire mes commentaires à l'aide d'un service

Imaginez que vous avez un 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...
  }
}

Nos enfants sont comme

    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;
      }
    
    }

Notre parent aime

<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>

Voir la "variable de référence", nous utilisons ViewChild pour obtenir le composant

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()
  }
}

Vous pouvez voir dans un laid stackblitz

1
Eliseo 1 sept. 2020 à 08:03

Comme le dit le dicton "Il y a plusieurs façons d'écorcher un chat", il en va de même ici. Angular vous donne les outils et vous laisse l'architecture.

Les multiples onglets de la barre latérale signifient que vous opteriez probablement pour une mise en page maître-détails.

Et vous pouvez faire le formulaire multiple et, comme vous l'avez déjà remarqué, vous devrez le synchroniser.

Cependant, je suggérerais d'utiliser un formulaire, qui engloberait toute la mise en page détaillée, et vous transmettriez l'instance de formulaire aux composants de détail.

Donc l'idée est que vous aurez un FormGroup dans votre composant parent, tout comme le bouton Save. Et vous l'initialisez essentiellement avec un FormGroup vide.

form = fb.group({});

Que vous transmettez ensuite à votre composant de vue de détail en tant que paramètre @Input et sur le ngOnInit() vous ajouteriez le FormControl

@Input() form: FormGroup;
ngOnInit() {
    this.form.addControl('enableLogging', new FormControl(this.settingsService.config.enableLogging));
    // other form controls
}

Le settingsService.config est votre source de vérité, c'est-à-dire la configuration renvoyée par votre réponse api.

Avoir un seul formulaire vous donnerait deux avantages:

  1. Vous n'auriez pas à vous soucier de la synchronisation des données de chaque formulaire et de leur consolidation.
  2. Puisque vous avez le bouton d'enregistrement unique, qui enregistrerait toutes les données, au lieu d'avoir enregistrer sur chaque onglet, avoir un seul formulaire, dans le composant parent, signifie que vous pouvez simplement le publier avec this.form.value sur le clic d'enregistrement bouton.
1
j4rey 30 août 2020 à 06:08