angular 2 видаляє всі елементи з масиву


86

У мене є масив форм всередині конструктора форм, і я динамічно змінюю форми, тобто при натисканні даних завантаження із програми 1 тощо.

Проблема, з якою я стикаюся, полягає в тому, що всі дані завантажуються, але дані у масиві форми залишаються і просто з’єднують старі елементи з новими.

Як я можу очистити цей формуляр, щоб мати лише нові елементи.

Я спробував це

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 не викликається при натисканні


Відповіді:


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+, використовується найкращий спосіб видалення всіх компонентів із FormArrayformArray.clear();
Ренан

2
Крім того, yourFormArray.setValue ([])); та yourFormGroup.setControl ('yourFormArray', []);
Оскар

1
до побачення перевірка при такому підході
Андре Елріко

@Renan Я використовую formControl
Emir Herrera

30

Або ви можете просто очистити елементи керування

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


6
"Arr.controls = [];" згадка справді чудова!
dotNetkow

@Pian, Тільки const arr = <FormArray> this.myForm.controls.arr; arr.controls = []; працює над очищенням масиву форми. TQ
chandoo

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

8

Angular v4.4, якщо вам потрібно зберегти те саме посилання на екземпляр FormArray, спробуйте наступне:

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

Хороший спосіб зберегти передплату, витягуючи елементи з масиву.
red_dorian

@mtpultz зверніть увагу на журнал змін ( stackoverflow.com/posts/41856927/revisions ) прийнятої відповіді. Коли я залишив цю відповідь, прийнята відповідь відрізнялася від поточної.
Олексій Дзейко,

8

Увага!

Документація Angular v6.1.7 FormArray говорить:

Щоб змінити елементи керування в масиві, використовуйте методи push, insert або removeAt у самому FormArray. Ці методи забезпечують належне відстеження елементів керування в ієрархії форми. Не модифікуйте масив AbstractControls, який використовується для створення екземпляра FormArray безпосередньо, оскільки це призводить до дивної та несподіваної поведінки, наприклад виявлення порушених змін.

Майте це на увазі, якщо ви використовуєте spliceфункцію безпосередньо на controlsмасиві як одну із запропонованих відповідей.

Використовувати removeAt функцію.

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

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

Thx Це працює ......
nos nart


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 (значення: будь-який [], {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 з попередньої роботи з демонтажу шахти - дуже просте використання кожного.


безумовно, це означає, що у вас має бути однакова кількість елементів у масиві?
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 ([]); }


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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.