Domanda Come aggiungere e rimuovere dinamicamente i campi modulo in Angular 2


Sto cercando di aggiungere i campi di input dinamicamente mentre l'utente fa clic sul pulsante Aggiungi e per ogni campo modulo deve esserci un pulsante Rimuovi, quando l'utente fa clic sui campi del modulo devono essere rimossi, ho bisogno di farlo utilizzando Angular 2, come Sono nuovo di Angular 2, per favore aiutami a completarlo

Quello che ho provato

Ho creato un set di campi (3 select box e 1 text box), creato un pulsante chiamato add fields, ma l'ho provato in 1.x angolare funziona bene ma in angular 2 non so come completarlo , questo è collegamento del mio pieno lavoro

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

41
2018-06-24 06:50


origine


risposte:


Sono passati alcuni mesi, ma ho pensato di fornire la mia soluzione basandomi su questo qui tutorial. Il nocciolo della questione è che è molto più facile da gestire una volta cambiato il modo in cui ti avvicini alle forme.

Per prima cosa, usa ReactiveFormsModule invece che o in aggiunta al normale FormsModule. Con i moduli reattivi crei i tuoi moduli nei tuoi componenti / servizi e poi li inserisca nella tua pagina invece della tua pagina generando il modulo stesso. È un po 'più codice, ma è molto più testabile, molto più flessibile e, per quanto posso dire, il modo migliore per fare un sacco di moduli non banali.

Il risultato finale sarà un po 'come questo, concettualmente:

  • Hai una base FormGroup con qualunque cosa FormControl istanze necessarie per la totalità del modulo. Ad esempio, come nel tutorial a cui mi sono collegato, diciamo che vuoi un modulo in cui un utente può inserire il proprio nome una volta e quindi un numero qualsiasi di indirizzi. Tutti gli input sul campo una tantum si trovano in questo gruppo di moduli di base.

  • Dentro quello FormGroup istanza ci sarà uno o più FormArray le istanze. UN FormArray è fondamentalmente un modo per raggruppare più controlli insieme e scorrere su di essi. Puoi anche mettere più FormGroup istanze nell'array e utilizzare quelle come essenzialmente "mini-form" nidificate nella forma più grande.

  • Nidificando più FormGroup e / o FormControl istanze all'interno di una dinamica FormArray, puoi controllare la validità e gestire il modulo come un unico pezzo grande reattivo composto da diverse parti dinamiche. Ad esempio, se si desidera verificare se ogni singolo input è valido prima di consentire all'utente di inviare, la validità di una sottomodulo si "bolla" al modulo di livello superiore e l'intero modulo diventa non valido, rendendo più semplice gestire gli input dinamici.

  • Come un FormArray è, in sostanza, un wrapper attorno all'interfaccia dell'array ma per i pezzi del modulo, è possibile premere, inserire, inserire e rimuovere i controlli in qualsiasi momento senza ricreare il modulo o eseguire interazioni complesse.

Nel caso in cui il tutorial che ho linkato si interrompa, ecco alcuni esempi di codice che puoi implementare tu stesso (i miei esempi usano TypeScript) che illustrano le idee di base:

Codice componente base:

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

Codice sottocomponente: (uno per ogni nuovo campo di input, per mantenere le cose pulite)

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 HTML del componente

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

HTML sottocomponente

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

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

Nel codice precedente ho fondamentalmente un componente che rappresenta la base del modulo e quindi ciascun sottocomponente ne gestisce il proprio FormGroupistanza all'interno del FormArray situato all'interno della base FormGroup. Il modello di base passa lungo il sottogruppo al sottocomponente e quindi è possibile gestire la convalida per l'intero modulo in modo dinamico.

Inoltre, questo rende banale riordinare il componente inserendolo e rimuovendolo strategicamente dal modulo. Funziona con (apparentemente) un numero qualsiasi di input in quanto non sono in conflitto con i nomi (un grosso svantaggio di moduli basati su template, per quanto ne so) e si conserva ancora una buona convalida automatica. L'unico "svantaggio" di questo approccio è, oltre a scrivere un po 'più di codice, che devi reimparare come funzionano le forme. Tuttavia, questo aprirà la possibilità di forme molto più grandi e più dinamiche man mano che andrai avanti.

Se avete domande o volete segnalare alcuni errori, andare avanti. Ho appena digitato il codice sopra basato su qualcosa che ho fatto io stesso la scorsa settimana con i nomi modificati e altri misc. proprietà lasciate fuori, ma dovrebbe essere semplice. L'unica grande differenza tra il codice precedente e il mio è che ho spostato tutti i moduli in un servizio separato chiamato dal componente, quindi è un po 'meno disordinato.


122
2017-09-26 01:43