kątowy 2 usuwa wszystkie elementy z tablicy

86

Mam tablicę formularzy wewnątrz konstruktora formularzy i dynamicznie zmieniam formularze, tj. Ładowanie danych z aplikacji 1 po kliknięciu itp.

Problem, który mam, polega na tym, że wszystkie dane są ładowane, ale dane w formarray pozostają i po prostu łączą stare elementy z nowymi.

Jak wyczyścić tę tablicę, aby mieć tylko nowe elementy.

Próbowałem tego

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

ale to nie działa.

Jakieś pomysły? dzięki

w 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 nie jest wywoływany po kliknięciu

Karl O'Connor
źródło
Powiązany problem jest śledzony tutaj w repozytorium Angular
E. Sundin

Odpowiedzi:

145

Miałem ten sam problem. Istnieją dwa sposoby rozwiązania tego problemu.

Zachowaj subskrypcję

Możesz ręcznie wyczyścić każdy element FormArray, wywołując removeAt(i)funkcję w pętli.

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

Zaletą tego podejścia jest to, że żadne subskrypcje na Twoim koncie formArray, takie jak te zarejestrowane w serwisie formArray.valueChanges, nie zostaną utracone.

Więcej informacji można znaleźć w dokumentacji FormArray .


Czystsza metoda (ale łamie odniesienia do subskrypcji)

Możesz zastąpić cały FormArray nowym.

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

Takie podejście powoduje problem, jeśli subskrybujesz to, co formArray.valueChangesobserwowalne! Jeśli zastąpisz FromArray nową tablicą, utracisz odwołanie do obserwowalnego, które subskrybujesz.

CamelD
źródło
67
Od Angular 8+ preferowanym sposobem usuwania wszystkich komponentów z FormArray jest użycieformArray.clear();
Renan
2
Ponadto yourFormArray.setValue ([])); i yourFormGroup.setControl ('yourFormArray', []);
Oscar
1
pa pa pa walidacja z takim podejściem
Andre Elrico,
@Renan Używam formControl
Emir Herrera
29

Możesz też po prostu wyczyścić elementy sterujące

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

Dodać coś array

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

Wyczyść tablicę

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

Gdy masz zaznaczonych i wyczyszczonych wiele opcji, czasami nie aktualizuje to widoku. Obejściem problemu jest dodanie

arr.removeAt(0)

AKTUALIZACJA

Bardziej eleganckim rozwiązaniem do używania tablic formularzy jest użycie metody pobierającej na początku klasy, a następnie można uzyskać do niej dostęp.

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

I użyć go w szablonie

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

Resetowanie:

inFormArray.reset();

Pchać:

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

Usuń wartość w indeksie: 1

inFormArray.removeAt(1);

AKTUALIZACJA 2:

Pobierz częściowy obiekt, pobierz wszystkie błędy jako JSON i wiele innych funkcji, użyj NaoFormsModule

Pian0_M4n
źródło
5
Element „arr.controls = [];” wzmianka jest naprawdę świetna!
dotNetkow
@Pian, Only const arr = <FormArray> this.myForm.controls.arr; arr.controls = []; pracuje nad wyczyszczeniem tablicy formularza. TQ
chandoo
inFormArray.at(1).remove(); daje mi [ts] Property 'remove' does not exist on type 'AbstractControl'.błąd transpilera.
zgue
@ Pian0_M4n w twoim szablonie, let c of inFormArraypowinno być let c of inFormArray.controls?
wal
22

Od Angular 8+ możesz użyć clear()do usunięcia wszystkich kontrolek w FormArray:

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

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

W przypadku poprzednich wersji zalecany sposób to:

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

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

crappylime
źródło
1
Dziękuję za wspomnienie o Angular 8+.
Patrick Hillert,
10

Kątowy 8

po prostu użyj clear()metody na formArrays:

(this.invoiceForm.controls['other_Partners'] as FormArray).clear();
MajiD
źródło
8

Angular v4.4, jeśli chcesz zapisać to samo odniesienie do instancji FormArray, spróbuj tego:

purgeForm(form: FormArray) {
  while (0 !== form.length) {
    form.removeAt(0);
  }
}
Alex Dzeiko
źródło
Dobry sposób na zachowanie subskrypcji podczas wyrzucania elementów z tablicy.
red_dorian
@mtpultz zwróć uwagę na dziennik zmian ( stackoverflow.com/posts/41856927/revisions ) zaakceptowanej odpowiedzi. Kiedy zostawiłem tę odpowiedź, przyjęta odpowiedź różniła się od aktualnej.
Alex Dzeiko
8

Ostrzeżenie!

Dokumentacja Angular v6.1.7 FormArray mówi:

Aby zmienić kontrolki w tablicy, użyj metod push, insert lub removeAt w samym FormArray. Te metody zapewniają prawidłowe śledzenie formantów w hierarchii formularza. Nie modyfikuj tablicy AbstractControls używanej do bezpośredniego tworzenia wystąpienia FormArray, ponieważ powoduje to dziwne i nieoczekiwane zachowanie, takie jak wykrywanie uszkodzonych zmian.

Pamiętaj o tym, jeśli używasz splicefunkcji bezpośrednio na controlstablicy jako jednej z sugerowanych odpowiedzi.

Użyj removeAtfunkcji.

  while (formArray.length !== 0) {
    formArray.removeAt(0)
  }
zgue
źródło
6

Możesz łatwo zdefiniować metodę pobierającą dla swojej tablicy i wyczyścić ją w następujący sposób:

  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
źródło
Dzięki, to działa ......
nos nart
5

Aktualizacja: Angular 8 w końcu uzyskał metodę czyszczenia Array FormArray.clear ()

słowik2k1
źródło
4

Od Angular 8 możesz użyć this.formArray.clear()do wyczyszczenia wszystkich wartości z tablicy formularza. To prostsza i wydajniejsza alternatywa dla usuwania wszystkich elementów jeden po drugim

Nikita Korba
źródło
4

Użyj FormArray.clear (), aby usunąć wszystkie elementy tablicy w FormArray

Anu Priya
źródło
3

Pod warunkiem, że struktura danych zostanie zastąpiona informacjami w tablicy dopasowaniami, które już tam są, możesz użyć 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 Łata wartość FormArray. Akceptuje tablicę, która pasuje do struktury kontrolki i zrobi wszystko, co w jej mocy, aby dopasować wartości do odpowiednich kontrolek w grupie.

Akceptuje zarówno super-zestawy, jak i podzbiory tablicy bez zgłaszania błędu.

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

Alternatywnie możesz użyć reset

reset (value ?: any, {onlySelf, emitEvent} ?: {onlySelf ?: boolean, emitEvent ?: boolean}): void Resetuje FormArray. Oznacza to domyślnie:

Tablica i wszystkie elementy potomne są zaznaczone jako nieskazitelne Tablica i wszystkie elementy potomne są oznaczane jako nietknięte Wartość wszystkich elementów podrzędnych będzie zerowa lub pusta Mapa Można również zresetować do określonego stanu formularza poprzez przekazanie tablicy stanów, które pasują do struktury kontrolki . Stan może być wartością samodzielną lub obiektem stanu formularza z wartością i stanem wyłączenia.

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

LUB

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

Oto rozwidlone demo Plunkera z niektórych moich wcześniejszych prac demonstrujące bardzo proste wykorzystanie każdego z nich.

silentsod
źródło
z pewnością oznacza to, że musisz mieć dokładnie taką samą liczbę elementów w tablicy?
Simon_Weaver
2

Nigdy nie próbowałem używać formArray, zawsze pracowałem z FormGroup i możesz usunąć wszystkie kontrolki za pomocą:

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

będąc formGroup wystąpieniem FormGroup.

Pianisimo
źródło
1

Jestem bardzo spóźniony, ale znalazłem inny sposób, w którym nie trzeba mieć pętli. możesz zresetować tablicę, ustawiając kontrolkę tablicy na pustą.

Poniższy kod zresetuje twoją macierz.

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

Jak gdyby
źródło
0

Podczas gdy pętla zajmie dużo czasu, aby usunąć wszystkie elementy, jeśli tablica zawiera 100 elementów. Możesz opróżnić zarówno kontrolki, jak i właściwości wartości FormArray, jak poniżej.

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

user3067875
źródło
0

Aby kod był czysty, stworzyłem następującą metodę rozszerzenia dla każdego, kto używa Angular 7 i niższych. Można to również wykorzystać do rozszerzenia innych funkcji formularzy reaktywnych.

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
źródło