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는 클릭시 호출되지 않습니다.


이와 관련된 문제는 각도의 repo 여기에 추적
E. Sundin은을

답변:


148

나는 같은 문제가 있었다. 이 문제를 해결하는 방법에는 두 가지가 있습니다.

구독 유지

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를 새 배열로 바꾸면 구독중인 Observable에 대한 참조를 잃게됩니다.


73
Angular 8+부터 FormArray에서 모든 구성 요소를 제거하는 선호되는 방법은 다음을 사용하는 것입니다formArray.clear();
Renan

2
또한 yourFormArray.setValue ([])); 그리고 yourFormGroup.setControl ( 'yourFormArray', []);
Oscar

1
이 방법 안녕히 검증
앙드레 Elrico

내가 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)

최신 정보

양식 배열을 사용하는 더 우아한 솔루션은 클래스 맨 위에있는 getter를 사용하여 액세스 할 수 있습니다.

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'.transpiler 오류가 발생했습니다.
zgue

템플릿에서 Pian0_M4n @ let c of inFormArray해야 let c of inFormArray.controls?

23

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+를 언급 해주셔서 감사합니다.
패트릭 Hillert

11

각도 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 ) 를 참고하십시오 . 이 대답을 떠났을 때 수락 된 대답은 현재와 달랐습니다.
Alex Dzeiko

8

경고!

Angular v6.1.7 FormArray 문서 는 다음과 같이 말합니다.

배열의 컨트롤을 변경하려면 FormArray 자체에서 push, insert 또는 removeAt 메서드를 사용합니다. 이러한 메서드는 폼의 계층 구조에서 컨트롤이 제대로 추적되도록합니다. FormArray를 직접 인스턴스화하는 데 사용되는 AbstractControls의 배열을 수정하지 마십시오. 변경 감지 중단과 같은 이상하고 예기치 않은 동작이 발생할 수 있습니다.

제안 된 답변 중 하나로 배열에서 splice직접 함수를 사용하는 경우이를 염두에 두십시오 controls.

removeAt기능을 사용하십시오 .

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

6

배열에 대한 getter를 쉽게 정의하고 다음과 같이 지울 수 있습니다.

  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은 마침내 Array FormArray.clear ()를 지우는 방법을 얻었습니다.


5

FormArray.clear ()를 사용하여 FormArray에서 배열의 모든 요소를 ​​제거하십시오.


4

Angular 8부터는 this.formArray.clear()양식 배열의 모든 값을 지우는 데 사용할 수 있습니다 . 모든 요소를 ​​하나씩 제거하는 것보다 더 간단하고 효율적인 대안입니다.


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를 재설정합니다. 이것은 기본적으로 다음을 의미합니다.

배열과 모든 하위 항목이 원래 상태로 표시됨 배열과 모든 하위 항목이 변경되지 않은 상태로 표시됨 모든 하위 항목의 값은 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

코드를 깨끗하게 유지하기 위해 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;
}


1

나는 매우 늦었지만 루프가 필요하지 않은 다른 방법을 찾았습니다. 배열 제어를 빈 상태로 설정하여 배열을 재설정 할 수 있습니다.

아래 코드는 배열을 재설정합니다.

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


0

배열에 100 개의 항목이있는 경우 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.