UFO ET IT

Angular 2에서 양식 필드를 동적으로 추가하고 제거하는 방법

ufoet 2021. 1. 17. 11:36
반응형

Angular 2에서 양식 필드를 동적으로 추가하고 제거하는 방법


사용자가 추가 버튼을 클릭하는 동안 동적으로 입력 필드를 추가하려고합니다. 각 양식 필드에는 제거 버튼이 있어야합니다. 사용자가 양식 필드를 제거해야한다는 것을 클릭 할 때 Angular 2를 사용하여이를 수행해야합니다. 저는 Angular 2를 처음 사용합니다. 완성하도록 도와주세요.

내가 시도한 것

필드 세트 (선택 상자 3 개와 텍스트 상자 1 개)를 만들고 필드 추가라는 버튼을 만들었지 만 각도 1.x에서는 잘 작동했지만 각도 2에서는 완료하는 방법을 모르겠습니다. , 이것은 내 전체 작업의 링크 입니다.

app/app.component.ts
 import {
    Component
  }
from '@angular/core';
  @Component({
    selector: 'my-app',
    template: `
    <h1>{{title}}</h1>
    <div class="container">
    <button class="btn btn-success bt-sm">add</button>
    <form role="form" calss="form-inline">
    <div class="form-group col-xs-3">
    <label>Select State:</label>
    <select class="form-control" [(ngModel)]="rules.State" id="sel1">
            <option>State1</option>
            <option>State2</option>
            <option>State3</option>
            <option>State4</option>
</select>
     </div>
    <div class="form-group col-xs-3">
<label>Rule:</label>
     <input type="text" data-toggle="modal" data-target="#myModal" class="form-                   control">
    </div>
<div class="form-group col-xs-3">
<label>Pass State :</label>
    <select class="form-control" [(ngModel)]="rules.pass">
    <option>State1</option>
    <option>State2</option>
    <option>State3</option>
    <option>State4</option>
</select>
 </div>
 <div class="form-group col-xs-3">
    <label>Fail State:</label>
        <select class="form-control" [(ngModel)]="rules.fail">
        <option>State1</option>
        <option>State2</option>
        <option>State3</option>
     <option>State4</option>
     </select>
         </div>
    </form>
     </div>
 <div class="modal fade" id="myModal" role="dialog">
      <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                     <button type="button" class="close" data-dismiss="modal">&times    </button>
                    <h4 class="modal-title">Rules Configuration</h4>
                </div>
                <div class="modal-body">
                 <p>Rules</p>
                </div>
                 <div class="modal-footer">
                 <button type="button" class="btn btn-default" data-  dismiss="modal">Close</button>
                </div>
             </div>

                </div>
                 </div>
`
    })
    export class AppComponent {
            title = 'Rule Engine Demo';
          rules: Rules = {
                  State: '',
                  pass: '',
                 fail: ''
                };

이것은 몇 달 늦었지만 여기 튜토리얼을 기반으로 솔루션을 제공 할 것이라고 생각했습니다 . 요점은 양식에 접근하는 방식을 변경하면 관리하기가 훨씬 쉽다는 것입니다.

첫째, ReactiveFormsModule일반 FormsModule. 반응 형 양식을 사용하면 구성 요소 / 서비스에서 양식을 만든 다음 페이지에서 양식 자체를 생성하는 대신 페이지에 연결합니다. 약간 더 많은 코드이지만 훨씬 더 테스트 가능하고 훨씬 유연하며 사소하지 않은 많은 양식을 만드는 가장 좋은 방법을 말할 수 있습니다.

최종 결과는 개념적으로 다음과 같이 보일 것입니다.

  • 양식 전체에 필요한 인스턴스 가있는 하나의 기반 FormGroupFormControl있습니다. 예를 들어 내가 링크 한 튜토리얼에서와 같이 사용자가 이름을 한 번 입력 한 다음 원하는 수의 주소를 입력 할 수있는 양식을 원한다고 가정 해 보겠습니다. 모든 일회성 필드 입력은이 기본 양식 그룹에 있습니다.

  • 해당 FormGroup인스턴스 내부 에는 하나 이상의 FormArray인스턴스가 있습니다. A FormArray는 기본적으로 여러 컨트롤을 그룹화하고 반복하는 방법입니다. 또한 FormGroup배열 에 여러 인스턴스를 배치하고이를 더 큰 양식 내에 중첩 된 "미니 양식"으로 사용할 수도 있습니다.

  • 동적 내에 여러 FormGroup및 / 또는 FormControl인스턴스 를 중첩 FormArray하면 유효성을 제어하고 여러 동적 부분으로 구성된 하나의 크고 반응적인 부분으로 양식을 관리 할 수 ​​있습니다. 예를 들어, 사용자가 제출하도록 허용하기 전에 모든 단일 입력이 유효한지 확인하려는 경우 한 하위 양식의 유효성이 최상위 양식으로 "버블 링"되고 전체 양식이 무효화되어 쉽게 동적 입력을 관리합니다.

  • A는 것처럼 FormArray이며, 본질적으로 배열 인터페이스 주위하지만 형태로 조각의 래퍼, 당신은 밀어 수, 삽입 팝업 및 양식을 다시 복잡한 상호 작용을하지 않고 언제든지 컨트롤을 제거합니다.

링크 한 튜토리얼이 중단되는 경우 기본 아이디어를 설명하는 몇 가지 샘플 코드를 직접 구현할 수 있습니다 (내 예제에서는 TypeScript 사용).

기본 구성 요소 코드 :

import { Component, Input, OnInit } from '@angular/core';
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'my-form-component',
  templateUrl: './my-form.component.html'
})
export class MyFormComponent implements OnInit {
    @Input() inputArray: ArrayType[];
    myForm: FormGroup;

    constructor(private fb: FormBuilder) {}
    ngOnInit(): void {
        let newForm = this.fb.group({
            appearsOnce: ['InitialValue', [Validators.required, Validators.maxLength(25)]],
            formArray: this.fb.array([])
        });

        const arrayControl = <FormArray>newForm.controls['formArray'];
        this.inputArray.forEach(item => {
            let newGroup = this.fb.group({
                itemPropertyOne: ['InitialValue', [Validators.required]],
                itemPropertyTwo: ['InitialValue', [Validators.minLength(5), Validators.maxLength(20)]]
            });
            arrayControl.push(newGroup);
        });

        this.myForm = newForm;
    }
    addInput(): void {
        const arrayControl = <FormArray>this.myForm.controls['formArray'];
        let newGroup = this.fb.group({

            /* Fill this in identically to the one in ngOnInit */

        });
        arrayControl.push(newGroup);
    }
    delInput(index: number): void {
        const arrayControl = <FormArray>this.myForm.controls['formArray'];
        arrayControl.removeAt(index);
    }
    onSubmit(): void {
        console.log(this.myForm.value);
        // Your form value is outputted as a JavaScript object.
        // Parse it as JSON or take the values necessary to use as you like
    }
}

Sub-Component Code: (one for each new input field, to keep things clean)

import { Component, Input } from '@angular/core';
import { FormGroup } from '@angular/forms';

@Component({
    selector: 'my-form-sub-component',
    templateUrl: './my-form-sub-component.html'
})
export class MyFormSubComponent {
    @Input() myForm: FormGroup; // This component is passed a FormGroup from the base component template
}

Base Component HTML

<form [formGroup]="myForm" (ngSubmit)="onSubmit()" novalidate>
    <label>Appears Once:</label>
    <input type="text" formControlName="appearsOnce" />

    <div formArrayName="formArray">
        <div *ngFor="let control of myForm.controls['formArray'].controls; let i = index">
            <button type="button" (click)="delInput(i)">Delete</button>
            <my-form-sub-component [myForm]="myForm.controls.formArray.controls[i]"></my-form-sub-component>
        </div>
    </div>
    <button type="button" (click)="addInput()">Add</button>
    <button type="submit" [disabled]="!myForm.valid">Save</button>
</form>

Sub-Component HTML

<div [formGroup]="form">
    <label>Property One: </label>
    <input type="text" formControlName="propertyOne"/>

    <label >Property Two: </label>
    <input type="number" formControlName="propertyTwo"/>
</div>

In the above code I basically have a component that represents the base of the form and then each sub-component manages its own FormGroup instance within the FormArray situated inside the base FormGroup. The base template passes along the sub-group to the sub-component and then you can handle validation for the entire form dynamically.

Also, this makes it trivial to re-order component by strategically inserting and removing them from the form. It works with (seemingly) any number of inputs as they don't conflict with names (a big downside of template-driven forms as far as I'm aware) and you still retain pretty much automatic validation. The only "downside" of this approach is, besides writing a little more code, you do have to relearn how forms work. However, this will open up possibilities for much larger and more dynamic forms as you go on.

If you have any questions or want to point out some errors, go ahead. I just typed up the above code based on something I did myself this past week with the names changed and other misc. properties left out, but it should be straightforward. The only major difference between the above code and my own is that I moved all of the form-building to a separate service that's called from the component so it's a bit less messy.


addAccordian(type, data) { console.log(type, data);

let form = this.form;

if (!form.controls[type]) {
  let ownerAccordian = new FormArray([]);
  const group = new FormGroup({});
  ownerAccordian.push(
    this.applicationService.createControlWithGroup(data, group)
  );
  form.controls[type] = ownerAccordian;
} else {
  const group = new FormGroup({});
  (<FormArray>form.get(type)).push(
    this.applicationService.createControlWithGroup(data, group)
  );
}
console.log(this.form);

}

ReferenceURL : https://stackoverflow.com/questions/38007236/how-to-dynamically-add-and-remove-form-fields-in-angular-2

반응형