angular 2 supprime tous les éléments d'un formulaire

86

J'ai un tableau de formulaires dans un formbuilder et je change dynamiquement les formulaires, c'est-à-dire en cliquant sur les données de chargement de l'application 1, etc.

Le problème que je rencontre est que toutes les données se chargent mais que les données du formarray restent et concatent simplement les anciens éléments avec les nouveaux.

Comment effacer ce formulaire pour n'avoir que les nouveaux éléments.

J'ai essayé ça

const control2 = <FormArray>this.registerForm.controls['other_Partners'];
        control2.setValue([]);

mais ça ne marche pas.

Des idées? Merci

dans nginit

ngOnInit(): void {
this.route.params.subscribe(params => { alert(params['id']);
            if (params['id']) {
                this.id = Number.parseInt(params['id']);
            }
            else { this.id = null;}
          });
if (this.id != null && this.id != NaN) {
            alert(this.id);
            this.editApplication();
            this.getApplication(this.id);
        }
        else
        {
            this.newApplication();
        }

}

onSelect(Editedapplication: Application) {
 this.router.navigate(['/apply', Editedapplication.id]);
}

editApplication() {
      
        this.registerForm = this.formBuilder.group({
              id: null,
            type_of_proposal: ['', Validators.required],
            title: ['', [Validators.required, Validators.minLength(5)]],
            lead_teaching_fellow: ['', [Validators.required, Validators.minLength(5)]],
            description: ['', [Validators.required, Validators.minLength(5)]],
            status: '',
            userID: JSON.parse(localStorage.getItem('currentUser')).username,
            contactEmail: JSON.parse(localStorage.getItem('currentUser')).email,
            forename: JSON.parse(localStorage.getItem('currentUser')).firstname,
            surname: JSON.parse(localStorage.getItem('currentUser')).surname,
            line_manager_discussion: true,
            document_url: '',
            keywords: ['', [Validators.required, Validators.minLength(5)]],
            financial_Details: this.formBuilder.group({
                  id: null,
                buying_expertise_description: ['', [Validators.required, Validators.minLength(2)]],
                buying_expertise_cost: ['', [Validators.required]],
                buying_out_teaching_fellow_cost: ['', [Validators.required]],
                buying_out_teaching_fellow_desc: ['', [Validators.required, Validators.minLength(2)]],
                travel_desc: ['', [Validators.required, Validators.minLength(2)]],
                travel_cost: ['', [Validators.required]],
                conference_details_desc: ['', [Validators.required, Validators.minLength(2)]],
                conference_details_cost: ['', [Validators.required]],
            }),

            partners: this.formBuilder.array
                (
                [
                    //this.initEditPartner(),
                    //this.initEditPartner()
                    // this.initMultiplePartners(1)
                ]
                ),
            other_Partners: this.formBuilder.array([
                //this.initEditOther_Partners(),
            ])
           
        });
       
    }

getApplication(id)
    {
        

        this.applicationService.getAppById(id, JSON.parse(localStorage.getItem('currentUser')).username)
            .subscribe(Response => {
               
                    if (Response.json() == false) {
                        this.router.navigateByUrl('/');
                    }
                    else {
                        this.application = Response.json();  
                          for (var i = 0; i < this.application.partners.length;i++)
                          {
                                this.addPartner();
                          }
                          for (var i = 0; i < this.application.other_Partners.length; i++) {
                              this.addOther_Partner();
                          }

                          this.getDisabledStatus(Response.json().status);
                        (<FormGroup>this.registerForm)
                            .setValue(Response.json(), { onlySelf: true }); 
                      }

                }
         
        );

       
        
        

       
    }

ngonitit n'est pas appelé au clic

Karl O'Connor
la source
Un problème connexe est suivi ici sur le repo angulaire
E. Sundin

Réponses:

145

J'ai eu le même problème. Il existe deux façons de résoudre ce problème.

Préserver l'abonnement

Vous pouvez effacer manuellement chaque élément FormArray en appelant la removeAt(i)fonction dans une boucle.

clearFormArray = (formArray: FormArray) => {
  while (formArray.length !== 0) {
    formArray.removeAt(0)
  }
}

L'avantage de cette approche est que tous les abonnements sur votre formArray, comme celui enregistré avec formArray.valueChanges, ne seront pas perdus.

Consultez la documentation FormArray pour plus d'informations.


Méthode plus propre (mais rompt les références d'abonnement)

Vous pouvez remplacer tout FormArray par un nouveau.

clearFormArray = (formArray: FormArray) => {
  formArray = this.formBuilder.array([]);
}

Cette approche pose un problème si vous êtes abonné à l' formArray.valueChangesobservable! Si vous remplacez FromArray par un nouveau tableau, vous perdrez la référence à l'observable à laquelle vous êtes abonné.

Chameau
la source
67
À partir de Angular 8+, la méthode préférée pour supprimer tous les composants d'un FormArray est d'utiliserformArray.clear();
Renan
2
En outre, yourFormArray.setValue ([])); et yourFormGroup.setControl ('yourFormArray', []);
Oscar
1
bye bye validation avec cette approche
Andre Elrico
@Renan J'utilise formControl
Emir Herrera
29

Ou vous pouvez simplement effacer les commandes

this.myForm= {
     name: new FormControl(""),
     desc: new FormControl(""),
     arr: new FormArray([])
}

Ajoute quelque chose array

const arr = <FormArray>this.myForm.controls.arr;
arr.push(new FormControl("X"));

Effacer le tableau

const arr = <FormArray>this.myForm.controls.arr;
arr.controls = [];

Lorsque plusieurs choix sont sélectionnés et désactivés, parfois cela ne met pas à jour la vue. Une solution de contournement consiste à ajouter

arr.removeAt(0)

MISE À JOUR

Une solution plus élégante pour utiliser des tableaux de formulaires consiste à utiliser un getter en haut de votre classe, puis vous pouvez y accéder.

get inFormArray(): FormArray {
    this.myForm.get('inFormArray') as FormArray;
}

Et de l'utiliser dans un modèle

<div *ngFor="let c of inFormArray; let i = index;" [formGroup]="i">
other tags...
</div>

Réinitialiser:

inFormArray.reset();

Pousser:

inFormArray.push(new FormGroup({}));

Supprimer la valeur à l'index: 1

inFormArray.removeAt(1);

MISE À JOUR 2:

Obtenez un objet partiel, obtenez toutes les erreurs en JSON et de nombreuses autres fonctionnalités, utilisez le NaoFormsModule

Pian0_M4n
la source
5
Les "arr.controls = [];" la mention est vraiment super!
dotNetkow
@Pian, Uniquement const arr = <FormArray> this.myForm.controls.arr; arr.controls = []; travaille pour effacer le tableau de formulaire. TQ
chandoo
inFormArray.at(1).remove(); me donne une [ts] Property 'remove' does not exist on type 'AbstractControl'.erreur de transpilateur.
zgue le
@ Pian0_M4n dans votre modèle, let c of inFormArraydevrait être let c of inFormArray.controls?
wal
22

À partir d'Angular 8+, vous pouvez utiliser clear()pour supprimer tous les contrôles dans FormArray:

const arr = new FormArray([
   new FormControl(),
   new FormControl()
]);
console.log(arr.length);  // 2

arr.clear();
console.log(arr.length);  // 0

Pour les versions précédentes, la méthode recommandée est:

while (arr.length) {
   arr.removeAt(0);
}

https://angular.io/api/forms/FormArray#clear

merde
la source
1
Merci d'avoir mentionné Angular 8+ ici.
Patrick Hillert
10

Angulaire 8

utilisez simplement la clear()méthode sur formArrays:

(this.invoiceForm.controls['other_Partners'] as FormArray).clear();
MajiD
la source
8

Angular v4.4 si vous devez enregistrer la même référence à l'instance de FormArray, essayez ceci:

purgeForm(form: FormArray) {
  while (0 !== form.length) {
    form.removeAt(0);
  }
}
Alex Dzeiko
la source
Bon moyen de préserver l'abonnement tout en faisant sortir des éléments du tableau.
red_dorian
@mtpultz veuillez noter le journal des modifications ( stackoverflow.com/posts/41856927/revisions ) de la réponse acceptée. Au moment où je suis parti, cette réponse acceptée était différente de l'actuelle.
Alex Dzeiko
8

Attention!

La documentation Angular v6.1.7 FormArray dit:

Pour modifier les contrôles dans le tableau, utilisez les méthodes push, insert ou removeAt dans FormArray lui-même. Ces méthodes garantissent que les contrôles sont correctement suivis dans la hiérarchie du formulaire. Ne modifiez pas le tableau de AbstractControls utilisé pour instancier le FormArray directement, car cela entraînerait un comportement étrange et inattendu tel qu'une détection de modification interrompue.

Gardez cela à l'esprit si vous utilisez la splicefonction directement sur le controlstableau comme l'une des réponses suggérées.

Utilisez la removeAtfonction.

  while (formArray.length !== 0) {
    formArray.removeAt(0)
  }
zgue
la source
6

Vous pouvez facilement définir un getter pour votre tableau et l'effacer comme suit:

  formGroup: FormGroup    
  constructor(private fb: FormBuilder) { }

  ngOnInit() {
    this.formGroup = this.fb.group({
      sliders: this.fb.array([])
    })
  }
  get sliderForms() {
    return this.formGroup.get('sliders') as FormArray
  }

  clearAll() {
    this.formGroup.reset()
    this.sliderForms.clear()
  }
M.Reza
la source
Thx It works ......
nos nart
5

Mise à jour: Angular 8 a enfin obtenu une méthode pour effacer le tableau FormArray.clear ()

rossignol2k1
la source
4

Depuis Angular 8, vous pouvez utiliser this.formArray.clear()pour effacer toutes les valeurs du tableau de formulaire. C'est une alternative plus simple et plus efficace pour supprimer tous les éléments un par un

Nikita Korba
la source
4

Utilisez FormArray.clear () pour supprimer tous les éléments d'un tableau dans un FormArray

Anu Priya
la source
3

Fourni la structure de données pour ce que vous allez remplacer les informations dans le tableau par correspond à ce qui est déjà là, vous pouvez utiliser patchValue

https://angular.io/docs/ts/latest/api/forms/index/FormArray-class.html#!#reset-anchor

patchValue (valeur: any [], {onlySelf, emitEvent} ?: {onlySelf ?: boolean, emitEvent ?: boolean}): void Corrige la valeur du FormArray. Il accepte un tableau qui correspond à la structure du contrôle et fera de son mieux pour faire correspondre les valeurs aux contrôles corrects du groupe.

Il accepte à la fois les super-ensembles et les sous-ensembles du tableau sans générer d'erreur.

const arr = new FormArray([
   new FormControl(),
   new FormControl()
]);
console.log(arr.value);   // [null, null]
arr.patchValue(['Nancy']);
console.log(arr.value);   // ['Nancy', null]

Vous pouvez également utiliser reset

reset (value ?: any, {onlySelf, emitEvent} ?: {onlySelf ?: boolean, emitEvent ?: boolean}): void Réinitialise le FormArray. Cela signifie par défaut:

Le tableau et tous les descendants sont marqués comme parfaits Le tableau et tous les descendants sont marqués intacts La valeur de tous les descendants sera null ou null maps Vous pouvez également réinitialiser à un état de formulaire spécifique en passant un tableau d'états correspondant à la structure du contrôle . L'état peut être une valeur autonome ou un objet d'état de formulaire avec à la fois une valeur et un état désactivé.

this.arr.reset(['name', 'last name']);
console.log(this.arr.value);  // ['name', 'last name']

OU

this.arr.reset([   {value: 'name', disabled: true},   'last' ]);
console.log(this.arr.value);  // ['name', 'last name']
console.log(this.arr.get(0).status);  // 'DISABLED'

Voici une démo de Plunker fourchue à partir de certains travaux antérieurs de la mine montrant une utilisation très simple de chacun.

silentsod
la source
cela signifie sûrement que vous devez avoir exactement le même nombre d'éléments dans le tableau?
Simon_Weaver
2

Je n'ai jamais essayé d'utiliser formArray, j'ai toujours travaillé avec FormGroup et vous pouvez supprimer tous les contrôles en utilisant:

Object.keys(this.formGroup.controls).forEach(key => {
          this.formGroup.removeControl(key);
        });

étant formGroup une instance de FormGroup.

Pianisimo
la source
1

Je suis très en retard mais j'ai trouvé un autre moyen de ne pas avoir de boucles. vous pouvez réinitialiser le tableau en définissant le contrôle du tableau sur vide.

Le code ci-dessous réinitialisera votre tableau.

this.form.setControl('name', this.fb.array([]))

Comme si
la source
0

La boucle While prendra beaucoup de temps pour supprimer tous les éléments si le tableau contient des centaines d'éléments. Vous pouvez vider les contrôles et les propriétés de valeur de FormArray comme ci-dessous.

clearFormArray = (formArray: FormArray) => {formArray.controls = []; formArray.setValue ([]); }

utilisateur3067875
la source
0

Pour garder le code propre, j'ai créé la méthode d'extension suivante pour toute personne utilisant Angular 7 et ci-dessous. Cela peut également être utilisé pour étendre toute autre fonctionnalité de Reactive Forms.

import { FormArray } from '@angular/forms';

declare module '@angular/forms/src/model' {
  interface FormArray {
    clearArray: () => FormArray;
  }
}

FormArray.prototype.clearArray = function () {
  const _self = this as FormArray;
  _self.controls = [];
  _self.setValue([]);
  _self.updateValueAndValidity();
  return _self;
}

Danielok1993
la source