angolare 2 rimuove tutti gli elementi da un formarray


86

Ho un array di moduli all'interno di un formbuilder e sto cambiando dinamicamente i moduli, cioè al clic carica i dati dall'applicazione 1 ecc.

Il problema che sto riscontrando è che tutti i dati vengono caricati ma i dati nel formarray rimangono e conciliano solo i vecchi elementi con i nuovi.

Come posso cancellare quel formarray per avere solo i nuovi elementi.

L'ho provato

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

ma non funziona.

Qualche idea? Grazie

in 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 non viene chiamato al clic


Risposte:


145

Ho avuto lo stesso problema. Esistono due modi per risolvere questo problema.

Mantieni l'abbonamento

È possibile cancellare manualmente ogni elemento FormArray chiamando la removeAt(i)funzione in un ciclo.

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

Il vantaggio di questo approccio è che qualsiasi abbonamento sul tuo formArray, come quello registrato con formArray.valueChanges, non andrà perso.

Consulta la documentazione di FormArray per ulteriori informazioni.


Metodo più pulito (ma interrompe i riferimenti di sottoscrizione)

Puoi sostituire l'intero FormArray con uno nuovo.

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

Questo approccio causa un problema se sei iscritto formArray.valueChangesall'osservabile! Se sostituisci FromArray con un nuovo array, perderai il riferimento all'osservabile a cui sei iscritto.


67
A partire da Angular 8+, il modo migliore per rimuovere tutti i componenti da un FormArray è usareformArray.clear();
Renan

2
Inoltre, yourFormArray.setValue ([])); e yourFormGroup.setControl ('yourFormArray', []);
Oscar

1
bye bye validation con questo approccio
Andre Elrico

@Renan Sto usando formControl
Emir Herrera

29

Oppure puoi semplicemente cancellare i controlli

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

Aggiungere qualcosa array

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

Cancella l'array

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

Quando hai più scelte selezionate e chiare, a volte non aggiorna la vista. Una soluzione alternativa è aggiungere

arr.removeAt(0)

AGGIORNARE

Una soluzione più elegante per utilizzare gli array di moduli è usare un getter all'inizio della classe e quindi puoi accedervi.

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

E per usarlo in un modello

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

Ripristina:

inFormArray.reset();

Spingere:

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

Rimuovi valore all'indice: 1

inFormArray.removeAt(1);

AGGIORNAMENTO 2:

Ottieni oggetto parziale, ottieni tutti gli errori come JSON e molte altre funzionalità, usa NaoFormsModule


5
"Arr.controls = [];" la menzione è davvero fantastica!
dotNetkow

@Pian, Solo const arr = <FormArray> this.myForm.controls.arr; arr.controls = []; sta lavorando per cancellare l'array del modulo. TQ
chandoo

inFormArray.at(1).remove(); mi dà un [ts] Property 'remove' does not exist on type 'AbstractControl'.errore del transpiler.
zgue

@ Pian0_M4n nel tuo modello, let c of inFormArraydovrebbe essere let c of inFormArray.controls?
wal

22

A partire da Angular 8+ puoi utilizzare clear()per rimuovere tutti i controlli nel FormArray:

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

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

Per le versioni precedenti il ​​metodo consigliato è:

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

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


1
Grazie per aver menzionato Angular 8+ qui.
Patrick Hillert

10

Angolare 8

usa semplicemente il clear()metodo su formArrays:

(this.invoiceForm.controls['other_Partners'] as FormArray).clear();

8

Angular v4.4 se hai bisogno di salvare lo stesso riferimento all'istanza di FormArray prova questo:

purgeForm(form: FormArray) {
  while (0 !== form.length) {
    form.removeAt(0);
  }
}

Un buon modo per preservare l'abbonamento mentre estrae gli elementi dall'array.
red_dorian

@mtpultz si prega di notare il changelog ( stackoverflow.com/posts/41856927/revisions ) della risposta accettata. Nel momento in cui ho lasciato questa risposta, la risposta accettata era diversa da quella attuale.
Alex Dzeiko

8

Avvertimento!

La documentazione di Angular v6.1.7 FormArray dice:

Per modificare i controlli nella matrice, utilizza i metodi push, insert o removeAt in FormArray stesso. Questi metodi assicurano che i controlli siano tracciati correttamente nella gerarchia del modulo. Non modificare la matrice di AbstractControls utilizzata per creare direttamente un'istanza di FormArray, poiché ciò si traduce in comportamenti strani e imprevisti come il rilevamento di modifiche interrotte.

Tienilo a mente se stai usando la splicefunzione direttamente controlssull'array come una delle risposte suggerite.

Usa la removeAtfunzione.

  while (formArray.length !== 0) {
    formArray.removeAt(0)
  }

6

Puoi facilmente definire un getter per il tuo array e cancellarlo come segue:

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

Grazie funziona ...
nn.

5

Aggiornamento: Angular 8 ha finalmente ottenuto il metodo per cancellare Array FormArray.clear ()


4

Da Angular 8 è possibile utilizzare this.formArray.clear()per cancellare tutti i valori nella matrice del modulo. È un'alternativa più semplice ed efficiente alla rimozione di tutti gli elementi uno per uno


4

Usa FormArray.clear () per rimuovere tutti gli elementi di un array in un FormArray


3

Fornito la struttura dei dati per ciò che sostituirai le informazioni nell'array con corrispondenze a ciò che è già lì che puoi usare patchValue

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

patchValue (value: any [], {onlySelf, emitEvent} ?: {onlySelf ?: boolean, emitEvent ?: boolean}): void Corregge il valore di FormArray. Accetta un array che corrisponde alla struttura del controllo e farà del suo meglio per abbinare i valori ai controlli corretti nel gruppo.

Accetta sia superinsiemi che sottoinsiemi dell'array senza generare errori.

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

In alternativa potresti usare reset

reset (value ?: any, {onlySelf, emitEvent} ?: {onlySelf ?: boolean, emitEvent ?: boolean}): void Reimposta il FormArray. Ciò significa per impostazione predefinita:

L'array e tutti i discendenti sono contrassegnati come incontaminati L'array e tutti i discendenti sono contrassegnati come intatti Il valore di tutti i discendenti sarà nullo o mappe nulle Puoi anche ripristinare uno stato della forma specifico passando un array di stati che corrisponde alla struttura del controllo . Lo stato può essere un valore autonomo o un oggetto stato del modulo con un valore e uno stato disabilitato.

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

O

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

Ecco una demo di Plunker biforcuta da un mio lavoro precedente che mostra un utilizzo molto semplice di ciascuno.


sicuramente questo significa che devi avere lo stesso identico numero di elementi nell'array?
Simon_Weaver

2

Non ho mai provato a utilizzare formArray, ho sempre lavorato con FormGroup e puoi rimuovere tutti i controlli usando:

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

essendo formGroup un'istanza di FormGroup.


1

Sono molto in ritardo ma ho trovato un altro modo in cui non è necessario avere loop. è possibile ripristinare l'array impostando il controllo dell'array su vuoto.

Il codice sottostante ripristinerà l'array.

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


0

Il ciclo While impiegherà molto tempo per eliminare tutti gli elementi se l'array ha centinaia di elementi. Puoi svuotare sia i controlli che le proprietà dei valori di FormArray come di seguito.

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


0

Per mantenere pulito il codice ho creato il seguente metodo di estensione per chiunque utilizzi Angular 7 e versioni precedenti. Può essere utilizzato anche per estendere qualsiasi altra funzionalità di 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;
}

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.