angular 2 удалить все элементы из массива

86

У меня есть массив форм внутри formbuilder, и я динамически меняю формы, то есть при загрузке данных из приложения 1 и т. Д.

Проблема, с которой я сталкиваюсь, заключается в том, что все данные загружаются, но данные в массиве форм остаются и просто объединяют старые элементы с новыми.

Как мне очистить этот formarray, чтобы в нем были только новые элементы.

Я пробовал это

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

но это не работает.

Любые идеи? Благодарность

в 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 не вызывается при нажатии

Карл О'Коннор
источник
Связанная с этим проблема отслеживается здесь, в репозитории Angular
Э. Сундин

Ответы:

145

У меня была такая же проблема. Есть два способа решить эту проблему.

Сохранить подписку

Вы можете вручную очистить каждый элемент FormArray, вызвав removeAt(i)функцию в цикле.

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

Преимущество этого подхода заключается в том, что любые подписки на вашем сайте formArray, например, зарегистрированные formArray.valueChanges, не будут потеряны.

Дополнительную информацию см. В документации FormArray .


Более чистый метод (но ломает ссылки на подписку)

Вы можете заменить весь FormArray на новый.

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

Этот подход вызывает проблему, если вы подписаны на formArray.valueChangesнаблюдаемое! Если вы замените FromArray новым массивом, вы потеряете ссылку на наблюдаемый объект, на который вы подписаны.

Верблюд
источник
67
Начиная с Angular 8+, предпочтительным способом удаления всех компонентов из FormArray является использованиеformArray.clear();
Ренан
2
Также yourFormArray.setValue ([])); и yourFormGroup.setControl ('yourFormArray', []);
Оскар
1
до свидания, проверка с этим подходом
Андре Элрико
@Renan, я использую formControl
Эмир Эррера
29

Или вы можете просто очистить элементы управления

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

Добавить что - нибудь array

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

Очистить массив

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

Когда у вас выбрано и очищено несколько вариантов, иногда вид не обновляется. Обходной путь - добавить

arr.removeAt(0)

ОБНОВИТЬ

Более элегантное решение для использования массивов форм - это использование геттера в верхней части вашего класса, после чего вы можете получить к нему доступ.

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

И использовать его в шаблоне

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

Сброс настроек:

inFormArray.reset();

От себя:

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

Удалить значение по индексу: 1

inFormArray.removeAt(1);

ОБНОВЛЕНИЕ 2:

Получите частичный объект, получите все ошибки как JSON и многие другие функции, используйте NaoFormsModule

Pian0_M4n
источник
5
"Arr.controls = [];" упоминание действительно здорово!
dotNetkow 04
@Pian, только const arr = <FormArray> this.myForm.controls.arr; arr.controls = []; работает над очисткой массива формы. TQ
chandoo 05
inFormArray.at(1).remove(); дает мне [ts] Property 'remove' does not exist on type 'AbstractControl'.ошибку транспилятора.
zgue
@ Pian0_M4n в вашем шаблоне, let c of inFormArrayдолжно быть let c of inFormArray.controls?
wal
22

Начиная с Angular 8+ вы можете использовать clear()для удаления всех элементов управления в FormArray:

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

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

Для предыдущих версий рекомендуемый способ:

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

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

краппилим
источник
1
Спасибо, что упомянули здесь Angular 8+.
Патрик
10

Угловой 8

просто используйте clear()метод formArrays:

(this.invoiceForm.controls['other_Partners'] as FormArray).clear();
MajiD
источник
8

Angular v4.4, если вам нужно сохранить ту же ссылку на экземпляр FormArray, попробуйте следующее:

purgeForm(form: FormArray) {
  while (0 !== form.length) {
    form.removeAt(0);
  }
}
Алекс Дзейко
источник
Хороший способ сохранить подписку при извлечении элементов из массива.
red_dorian
@mtpultz обратите внимание на журнал изменений ( stackoverflow.com/posts/41856927/revisions ) принятого ответа. Когда я оставил этот ответ, принятый ответ отличался от текущего.
Alex Dzeiko
8

Предупреждение!

В документации Angular v6.1.7 FormArray говорится:

Чтобы изменить элементы управления в массиве, используйте методы push, insert или removeAt в самом FormArray. Эти методы обеспечивают правильное отслеживание элементов управления в иерархии формы. Не изменяйте массив AbstractControls, используемый для непосредственного создания экземпляра FormArray, так как это приведет к странному и неожиданному поведению, например обнаружению неисправных изменений.

Имейте это в виду, если вы используете spliceфункцию непосредственно в controlsмассиве в качестве одного из предложенных ответов.

Используйте removeAtфункцию.

  while (formArray.length !== 0) {
    formArray.removeAt(0)
  }
zgue
источник
6

Вы можете легко определить геттер для своего массива и очистить его следующим образом:

  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()
  }
М. Реза
источник
Спасибо, это работает ......
нарт
5

Обновление: в Angular 8 наконец-то появился метод очистки массива FormArray.clear ()

соловей
источник
4

Начиная с Angular 8 вы можете использовать this.formArray.clear()для очистки всех значений в массиве форм. Это более простая и эффективная альтернатива удалению всех элементов по одному.

Никита Корба
источник
4

Используйте FormArray.clear (), чтобы удалить все элементы массива в FormArray

Ану Прия
источник
3

При условии, что структура данных для того, что вы будете заменять информацию в массиве, соответствует тому, что уже есть, вы можете использовать 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 Исправляет значение FormArray. Он принимает массив, соответствующий структуре элемента управления, и сделает все возможное, чтобы сопоставить значения с правильными элементами управления в группе.

Он принимает как надмножества, так и подмножества массива без выдачи ошибки.

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

В качестве альтернативы вы можете использовать reset

reset (value ?: any, {onlySelf, emitEvent} ?: {onlySelf ?: boolean, emitEvent ?: boolean}): void Сбрасывает FormArray. По умолчанию это означает:

Массив и все потомки помечены как нетронутые Массив и все потомки помечены как нетронутые. Значение всех потомков будет нулевым или пустым. Вы также можете выполнить сброс до определенного состояния формы, передав массив состояний, который соответствует структуре элемента управления. . Состояние может быть отдельным значением или объектом состояния формы со значением и отключенным статусом.

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

ИЛИ

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

Вот разветвленная демонстрация Plunker из некоторых моих предыдущих работ, демонстрирующая очень простое использование каждого из них.

Silentsod
источник
наверняка это означает, что у вас должно быть одинаковое количество элементов в массиве?
Simon_Weaver
2

Я никогда не пробовал использовать formArray, я всегда работал с FormGroup, и вы можете удалить все элементы управления, используя:

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

будучи formGroup экземпляром FormGroup.

Пианисимо
источник
1

Я очень опоздал, но нашел другой способ, где петли не нужны. вы можете сбросить массив, установив элемент управления массивом на пустой.

Код ниже сбросит ваш массив.

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

Будто
источник
0

Циклу while потребуется много времени для удаления всех элементов, если в массиве есть 100 элементов. Вы можете очистить свойства элементов управления и значений FormArray, как показано ниже.

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

user3067875
источник
0

Чтобы код оставался чистым, я создал следующий метод расширения для всех, кто использует Angular 7 и ниже. Это также можно использовать для расширения любых других функций реактивных форм.

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

Даниелок1993
источник