web-dev-qa-db-fra.com

Même formulaire pour créer et éditer des données Angular 4

Voici un formulaire avec deux champs de saisie liés de manière. L'objectif était de créer le même formulaire pour éditer et créer des données. Cela a été accompli, mais je suis presque sûr qu'il pourrait y avoir une meilleure façon de le faire (comme utiliser les fonctionnalités de AbstractControl). Un correctif me manque également - si on clique sur clickEdit(), il faut mettre à jour les valeurs du formulaire avec cet objet que l'utilisateur souhaite modifier. Merci pour toute aide et surtout explications sur AbstractControl et NgModel ..

<div>
<form (ngSubmit)="clicked ? onEditSubmit($event) : onRegisterSubmit($event)" [formGroup] = "form">
  <div class="form-group">
    <label>Full Name</label>
    <input type="text" [(ngModel)]="fullname" formControlName="fullname" class="form-control" >

  </div>
  <div class="form-group">
    <label>Username</label>
    <input type="text" [(ngModel)]="username" formControlName="username" class="form-control" >
  </div>
  <div class="form-group">
    <label>Email</label>
    <input type="text" [(ngModel)]="email" formControlName="email" class="form-control" >
  </div>
  <div class="form-group">
    <label>Password</label>
    <input type="password" [(ngModel)]="password" formControlName="password" class="form-control">
  </div>
  <button type="submit" class="btn btn-primary" [disabled]="!form.valid"> Submit </button>
</form>
</div>

<br>
<br>

<table  border="2" class="table table-striped">
<tr>
  <th>Full Name</th>
  <th>Username</th>
  <th>Email</th>
  <th>Password</th>
  <th>Delete</th>
  <th>Edit</th>
</tr>
<div > </div>
<tr *ngFor="let user of userDetails; index as i">
  <td>{{user.fullname}}</td>
  <td>{{user.username}}</td>
  <td>{{user.email}}</td>
  <td>{{user.password}}</td>
  <td><button (click)="userDelete()">X</button></td>
  <td><button (click)="clickEdit(i)">Edit</button></td>
</tr>
</table>

Et

import { Component } from '@angular/core';
import { initializeApp, database } from 'firebase';
import { FormControl, FormGroup, Validators } from '@angular/forms';


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {

  fullname : string;
  username : string;
  email : string;
  password : string;

  clicked = false;

  userDetails:Array<object>;

  form;

  ngOnInit() {
   this.userDetails=[];
    this.form = new FormGroup({
      fullname : new FormControl("", Validators.required),
      username : new FormControl("", Validators.required),
      email : new FormControl("", Validators.required),
      password : new FormControl("", Validators.required)
    });
  }

  onRegisterSubmit(e){
    let user = {
      fullname : this.fullname ,
      username : this.username,
      email : this.email ,
      password : this.password
    }
     this.userDetails.Push(user);
     this.clearInputFields(e);
   }

   editIndex = null;

  clickEdit(i){
    this.clicked = !this.clicked;
    this.editIndex = i;
  }

  onEditSubmit(e) {
    let editUser = {
      fullname : this.fullname ,
      username : this.username,
      email : this.email ,
      password : this.password
    }
    this.userDetails[this.editIndex] = editUser;
    this.clearInputFields(e);  
    this.clicked = !this.clicked;  
  }

  clearInputFields(e){
   let all = e.target.querySelectorAll('input');
    Object.keys(all).forEach(key => {
        console.log(all[key].value = '');   
    });    
  }
}
8

Je voudrais apporter quelques modifications à votre formulaire. ngModel est totalement redondant ici car vous utilisez une forme réactive. Utilisez-le à la place et supprimez tous les ngModel. L'objet que vous obtenez du formulaire correspond à votre user, donc ce que vous pouvez faire, c'est simplement pousser cette valeur telle quelle dans le tableau.

Votre modèle devrait donc ressembler à ceci (raccourci, comme le reste du code):

<form (ngSubmit)="onRegisterSubmit(form)" [formGroup] = "form">
  <input type="text" formControlName="username" class="form-control" >
  <input type="submit" class="btn btn-primary" value="Submit" [disabled]="!form.valid">
</form>

Dans la construction du formulaire, j'ai utilisé dans ce cas un champ caché, qui est également exclu de l'objet de formulaire car il est disabled. C'est une aide pour nous, donc nous pouvons différencier s'il s'agit d'un nouveau user, ou si nous éditons un user. La valeur contient l'index du user de votre tableau. Donc, si cette valeur existe, nous savons mettre à jour l'objet dans le tableau, si la valeur n'existe pas, poussons l'utilisateur vers le tableau.

Cela pourrait être résolu de nombreuses façons, mais ci-dessus est une option.

this.form = this.fb.group({
  index: [{value: null, disabled:true}]
  username : ['', Validators.required],
  email : ['', Validators.required],
});

Donc, selon ce qui précède, nous pouvons modifier le onRegisterSubmit pour ressembler à ceci:

onRegisterSubmit(form) {
  // since field is disabled, we need to use 'getRawValue'
  let index = form.getRawValue().index
  if(index != null) {
    this.userDetails[index] = form.value
  } else {
    this.userDetails.Push(form.value)      
  }
  this.form.reset() // reset form to empty
}

Lorsque nous voulons modifier un utilisateur, nous passons l'index et l'utilisateur dans le modèle

<tr *ngFor="let user of userDetails; let i = index">
  <td>{{user.username}}</td>
  <td>{{user.email}}</td>
  <td><button (click)="userEdit(user, i)">Edit</button></td>
</tr>

Et puis nous utilisons setValue (ou patchValue) pour entrer les champs avec les valeurs existantes:

userEdit(user, i) {
  this.form.setValue({
    index: i,
    username: user.username,
    email: user.email
  })
}

Ça devrait le faire! Alors maintenant, nous pouvons voir combien nous pourrions simplifier votre code et nous débarrasser de certaines choses inutiles! :)

13
AJT82