AngularのFormArrayからすべてのアイテムを削除します


87

FormBuilder内にフォーム配列があり、フォームを動的に変更しています。つまり、アプリケーション1からデータをロードするなどです。

私が抱えている問題は、すべてのデータが読み込まれるが、FormArrayのデータは残り、古いアイテムを新しいアイテムと連結するだけであるということです。

そのFormArrayをクリアして、新しいアイテムのみを含めるにはどうすればよいですか。

私はこれを試しました

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

しかし、それは機能しません。

何か案は?

ngOnInit(): void {
  this.route.params.subscribe(params => {
    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 });
      }
    });
}

クリック時にngOnInitが呼び出されない


回答:


148

私も同じ問題を抱えていました。この問題を解決するには2つの方法があります。

サブスクリプションを保持する

removeAt(i)ループ内で関数を呼び出すことにより、各FormArray要素を手動でクリアできます。

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

このアプローチの利点はformArray、に登録されているものなど、のサブスクリプションformArray.valueChangesが失われないことです。

詳細については、FormArrayのドキュメントを参照してください。


よりクリーンな方法(ただし、サブスクリプション参照を壊します)

FormArray全体を新しいものに置き換えることができます。

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

このアプローチは、formArray.valueChangesobservableにサブスクライブしている場合に問題を引き起こします!FromArrayを新しい配列に置き換えると、サブスクライブしているオブザーバブルへの参照が失われます。


73
Angular 8+以降、FormArrayからすべてのコンポーネントを削除するための推奨される方法は次のとおりですformArray.clear();
Renan

2
また、yourFormArray.setValue([])); およびyourFormGroup.setControl( 'yourFormArray'、[]);
オスカー

1
このアプローチによるバイバイ検証
AndreElrico19年

私はformControlを使用してい@Renan
エミールエレーラ

31

または、単にコントロールをクリアすることができます

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 2017

@ Pian、const arr = <FormArray> this.myForm.controls.arr;のみ arr.controls = []; フォーム配列をクリアするために働いています。TQ
チャンドゥー2018

inFormArray.at(1).remove(); 私に与え[ts] Property 'remove' does not exist on type 'AbstractControl'.transpilerエラーを。
zgue 2018

あなたのテンプレートでPian0_M4n @、let c of inFormArrayあるべきlet c of inFormArray.controls
wal 2018年

23

Angular 8clear()以降では、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
ここでAngular8 +について言及していただきありがとうございます。
PatrickHillert19年

11

Angular 8

clear()formArraysでメソッドを使用するだけです:

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

8

FormArrayのインスタンスへの同じ参照を保存する必要がある場合は、Angularv4.4を試してください。

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

配列から要素をポップしながらサブスクリプションを保持するための良い方法。
red_dorian

@mtpultzは、受け入れられた回答の変更ログ(stackoverflow.com/posts/41856927/revisions)に注意してください。私がこの答えを残したとき、受け入れられた答えは現在とは異なっていました。
AlexDzeiko19年

8

警告!

Angular v6.1.7FormArrayのドキュメントには次のように書かれています。

配列のコントロールを変更するには、FormArray自体のpush、insert、またはremoveAtメソッドを使用します。これらのメソッドは、コントロールがフォームの階層で適切に追跡されることを保証します。FormArrayを直接インスタンス化するために使用されるAbstractControlsの配列を変更しないでください。変更の検出の失敗など、奇妙で予期しない動作が発生します。

提案された答えの1つとしてsplicecontrols配列上で関数を直接使用している場合は、このことに注意してください。

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


5

FormArray.clear()を使用して、FormArray内の配列のすべての要素を削除します


4

Angular 8以降this.formArray.clear()、フォーム配列のすべての値をクリアするために使用できます。これは、すべての要素を1つずつ削除するよりも簡単で効率的な方法です。


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}):voidFormArrayの値にパッチを適用します。コントロールの構造に一致する配列を受け入れ、値をグループ内の正しいコントロールに一致させるために最善を尽くします。

エラーをスローすることなく、配列のスーパーセットとサブセットの両方を受け入れます。

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}):voidFormArrayをリセットします。これはデフォルトで次のことを意味します。

配列とすべての子孫は元の状態でマークされます配列とすべての子孫はそのままマークされますすべての子孫の値はnullまたはnullマップになりますコントロールの構造に一致する状態の配列を渡すことで、特定のフォーム状態にリセットすることもできます。状態は、スタンドアロン値、または値と無効ステータスの両方を持つフォーム状態オブジェクトにすることができます。

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

コードをクリーンに保つために、Angular7以下を使用するすべての人のために次の拡張メソッドを作成しました。これは、リアクティブフォームの他の機能を拡張するためにも使用できます。

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


1

私は非常に遅いですが、ループを持つ必要のない他の方法を見つけました。アレイコントロールを空に設定すると、アレイをリセットできます。

以下のコードは配列をリセットします。

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


0

配列に数百のアイテムがある場合、whileループはすべてのアイテムを削除するのに長い時間がかかります。以下のように、FormArrayのコントロールと値のプロパティの両方を空にすることができます。

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


0

Angular 7またはそれ以前のバージョンを使用していて、clear()メソッドにアクセスできない場合は、ループを実行せずにそれを実現する方法があります。

yourFormGroup.controls.youFormArrayName = new FormArray([]);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.