Angular ReactiveForms: produci un array di valori della casella di controllo?


104

Dato un elenco di caselle di controllo associate allo stesso formControlName, come posso produrre un array di valori di casella di controllo associati a formControl, piuttosto che semplicemente true/ false?

Esempio:

<form [formGroup]="checkboxGroup">
    <input type="checkbox" id="checkbox-1" value="value-1" formControlName="myValues" />
    <input type="checkbox" id="checkbox-2" value="value-2" formControlName="myValues" />
    <input type="checkbox" id="checkbox-3" value="value-2" formControlName="myValues" />
</form>

checkboxGroup.controls['myValues'].value attualmente produce:

true or false

Cosa voglio che produca:

['value-1', 'value-2', ...]

hai trovato qualche soluzione?
CP

Questo è probabilmente il modo più ingegnerizzato per creare caselle di controllo in una forma. Questo non è affatto semplice.
mwilson

8
Angolare. Tutto quello che sto cercando di fare è ottenere un gruppo radio-mat da legare nella mia forma reattiva. Non ricordo di aver lottato così tanto con angolare. Tutti gli articoli puntano alla stessa cosa. Non riesco proprio a farlo funzionare. Tutto il resto è semplicissimo. Probabilmente l'ho guardato troppo a lungo. Sembra ancora troppo complicato per un valore di matrice in un modulo.
mwilson

3
Sì, è stato terribile quando l'ho chiesto nel 2016, ed è ancora terribile nel 2019.
ReactingToAngularVues

3
Non sto aggiungendo una tonnellata a questa domanda, ma volevo che gli altri sapessero che mi sento allo stesso modo. Questa da sola è stata la parte più difficile nell'apprendimento delle forme reattive angolari. Sento che non dovrebbe essere affatto così difficile. Sono felice di vedere che non sono solo nella lotta, però. Quindi grazie per aver postato la domanda.
NorthStarCode

Risposte:


52

Con l'aiuto di silentsod answer, ho scritto una soluzione per ottenere valori invece di stati nel mio formBuilder.

Uso un metodo per aggiungere o rimuovere valori nel formArray. Potrebbe essere un pessimo approccio, ma funziona!

component.html

<div *ngFor="let choice of checks; let i=index" class="col-md-2">
  <label>
    <input type="checkbox" [value]="choice.value" (change)="onCheckChange($event)">
    {{choice.description}}
  </label>
</div>

component.ts

// For example, an array of choices
public checks: Array<ChoiceClass> = [
  {description: 'descr1', value: 'value1'},
  {description: "descr2", value: 'value2'},
  {description: "descr3", value: 'value3'}
];

initModelForm(): FormGroup{
  return this._fb.group({
    otherControls: [''],
    // The formArray, empty 
    myChoices: new FormArray([]),
  }
}

onCheckChange(event) {
  const formArray: FormArray = this.myForm.get('myChoices') as FormArray;

  /* Selected */
  if(event.target.checked){
    // Add a new control in the arrayForm
    formArray.push(new FormControl(event.target.value));
  }
  /* unselected */
  else{
    // find the unselected element
    let i: number = 0;

    formArray.controls.forEach((ctrl: FormControl) => {
      if(ctrl.value == event.target.value) {
        // Remove the unselected element from the arrayForm
        formArray.removeAt(i);
        return;
      }

      i++;
    });
  }
}

Quando invio il mio modulo, ad esempio, il mio modello ha il seguente aspetto:

  otherControls : "foo",
  myChoices : ['value1', 'value2']

Manca solo una cosa, una funzione per riempire il formArray se il tuo modello ha già valori controllati.


come faccio a verificare se la mia casella di controllo è selezionata quando carico i dati dopo aver utilizzato il tuo esempio per entrare in db?
Devora

In questa soluzione il modulo è sempre valido anche se la casella di controllo non è selezionata
Teja

myChoices: new FormArray([], Validators.required)
Bikram Nath

48

Ecco un buon posto per utilizzare FormArray https://angular.io/docs/ts/latest/api/forms/index/FormArray-class.html

Per iniziare, costruiremo la nostra gamma di controlli con un FormBuildero aggiungendo un fileFormArray

FormBuilder

this.checkboxGroup = _fb.group({
  myValues: _fb.array([true, false, true])
});

nuovo FormArray

let checkboxArray = new FormArray([
  new FormControl(true),
  new FormControl(false),
  new FormControl(true)]);

this.checkboxGroup = _fb.group({
  myValues: checkboxArray
});

Abbastanza facile da fare, ma poi cambieremo il nostro modello e lasceremo che il motore di modelli gestisca il modo in cui ci colleghiamo ai nostri controlli:

template.html

<form [formGroup]="checkboxGroup">
    <input *ngFor="let control of checkboxGroup.controls['myValues'].controls"
    type="checkbox" id="checkbox-1" value="value-1" [formControl]="control" />     
  </form>

Qui stiamo iterando sul nostro set di FormControlsnel nostro myValues FormArraye per ogni controllo ci leghiamo [formControl]a quel controllo invece che al FormArraycontrollo e <div>{{checkboxGroup.controls['myValues'].value}}</div>produce true,false,true, rendendo anche la sintassi del modello un po 'meno manuale.

Puoi usare questo esempio: http://plnkr.co/edit/a9OdMAq2YIwQFo7gixbj?p=preview per curiosare


1
probabilmente dovresti rimuovere id = "xxx", l'id dovrebbe essere univoco giusto?
PeiSong Xiong

1
per id potrebbe essere utilizzato l'indice *ngFor="let control of checkboxGroup.controls['myValues'].controls ; let i=index""
Mirza

9
Questo è interessante, ma produce una serie di caselle di controllo completamente generiche. Presumibilmente caricheresti in un array o qualcos'altro e assocerai ogni casella di controllo a qualche altro valore. Come si aggiunge, ad esempio, una stringa di testo da utilizzare in un'etichetta del modulo a ciascun controllo del modulo?
Askdesigners

NM L'ho appena mappato accanto a un array esterno: p
Askdesigners

@Askdesigners puoi pubblicare la tua soluzione per avere le caselle di controllo e le etichette?
eddygeek

25

È molto più facile farlo in Angular 6 rispetto alle versioni precedenti, anche quando le informazioni sulla casella di controllo sono popolate in modo asincrono da un'API.

La prima cosa da capire è che grazie al keyvaluepipe di Angular 6 non abbiamo più bisogno di usarlo FormArray, ma possiamo invece annidare un file FormGroup.

Per prima cosa, passa FormBuilder nel costruttore

constructor(
    private _formBuilder: FormBuilder,
) { }

Quindi inizializza il nostro modulo.

ngOnInit() {

    this.form = this._formBuilder.group({
        'checkboxes': this._formBuilder.group({}),
    });

}

Quando i dati delle nostre opzioni della casella di controllo sono disponibili, iterali e possiamo inserirli direttamente nel nidificato FormGroupcome un nome FormControl, senza dover fare affidamento su array di ricerca indicizzati numerici.

const checkboxes = <FormGroup>this.form.get('checkboxes');
options.forEach((option: any) => {
    checkboxes.addControl(option.title, new FormControl(true));
});

Infine, nel template dobbiamo solo iterare le keyvaluecaselle di controllo: nessuna aggiuntiva let index = i, e le caselle di controllo saranno automaticamente in ordine alfabetico: molto più pulite.

<form [formGroup]="form">

    <h3>Options</h3>

    <div formGroupName="checkboxes">

        <ul>
            <li *ngFor="let item of form.get('checkboxes').value | keyvalue">
                <label>
                    <input type="checkbox" [formControlName]="item.key" [value]="item.value" /> {{ item.key }}
                </label>
            </li>
        </ul>

    </div>

</form>

1
Molto utilizzabile anche in caso di un semplice array di valori di casella di controllo codificato. Quindi puoi aggiungere i controlli del modulo usando un ciclo for simile subito in ngOnInit (), e le caselle di controllo nel tuo modulo rifletteranno dinamicamente l'array dei valori della casella di controllo
Arjan

3
Questo ancora estratti [key1 = true, key2 = false, key3 = true]. Vogliamo ['key1', 'key3']
f.khantsis

@ f.khantsis Puoi farlo in questo modo: `const value = {key1: true, key2: false, key3: true}; const list = Object.entries (value) .filter (([_, isSelected]) => isSelected) .map (([key]) => key); console.log (elenco); `
zauni

1
Migliore soluzione imho. Si può piazzare l'incarico di const checkboxes = ..fuori pista;)
Bernoulli IT

Cosa succede quando la chiave dell'elemento è uguale a un altro campo nel modulo? Ad esempio, ho due diversi array di caselle di controllo, ciascuno con i tasti "Piccolo", "Medio" e "Grande"?
Newclique

9

Se stai cercando i valori delle caselle di controllo in formato JSON

{ "name": "", "countries": [ { "US": true }, { "Germany": true }, { "France": true } ] }

Esempio completo qui .

Mi scuso per aver utilizzato i nomi dei paesi come valori della casella di controllo anziché quelli nella domanda. Ulteriori spiegazioni -

Crea un FormGroup per il modulo

 createForm() {

    //Form Group for a Hero Form
    this.heroForm = this.fb.group({
      name: '',
      countries: this.fb.array([])
    });

    let countries=['US','Germany','France'];

    this.setCountries(countries);}
 }

Lascia che ogni casella di controllo sia un FormGroup creato da un oggetto la cui unica proprietà è il valore della casella di controllo.

 setCountries(countries:string[]) {

    //One Form Group for one country
    const countriesFGs = countries.map(country =>{
            let obj={};obj[country]=true;
            return this.fb.group(obj)
    });

    const countryFormArray = this.fb.array(countriesFGs);
    this.heroForm.setControl('countries', countryFormArray);
  }

La matrice di FormGroups per le caselle di controllo viene utilizzata per impostare il controllo per i "paesi" nel form padre.

  get countries(): FormArray {
      return this.heroForm.get('countries') as FormArray;
  };

Nel modello, utilizza una pipe per ottenere il nome per il controllo della casella di controllo

  <div formArrayName="countries" class="well well-lg">
      <div *ngFor="let country of countries.controls; let i=index" [formGroupName]="i" >
          <div *ngFor="let key of country.controls | mapToKeys" >
              <input type="checkbox" formControlName="{{key.key}}">{{key.key}}
          </div>
      </div>
  </div>

6

TL; DR

  1. Preferisco utilizzare FormGroup per popolare l'elenco delle caselle di controllo
  2. Scrivi un validatore personalizzato per verificare che almeno una casella di controllo sia stata selezionata
  3. Esempio funzionante https://stackblitz.com/edit/angular-validate-at-least-one-checkbox-was-selected

Anche questo mi ha colpito a volte, quindi ho provato entrambi gli approcci FormArray e FormGroup.

Il più delle volte, l'elenco delle caselle di controllo è stato compilato sul server e l'ho ricevuto tramite API. Ma a volte avrai un insieme statico di caselle di controllo con il tuo valore predefinito. Con ogni caso d'uso, verrà utilizzato il FormArray o FormGroup corrispondente.

Fondamentalmente FormArrayè una variante di FormGroup. La differenza fondamentale è che i suoi dati vengono serializzati come un array (invece di essere serializzati come un oggetto nel caso di FormGroup). Ciò potrebbe essere particolarmente utile quando non sai quanti controlli saranno presenti all'interno del gruppo, come i moduli dinamici.

Per semplicità, immagina di avere un semplice modulo di creazione del prodotto con

  • Una casella di testo del nome del prodotto richiesta.
  • Un elenco di categorie da cui selezionare, richiedeva che almeno una fosse selezionata. Supponiamo che l'elenco verrà recuperato dal server.

Per prima cosa, ho impostato un modulo con solo il nome del prodotto formControl. È un campo obbligatorio.

this.form = this.formBuilder.group({
    name: ["", Validators.required]
});

Poiché la categoria viene visualizzata in modo dinamico, dovrò aggiungere questi dati nel modulo più tardi, dopo che i dati erano pronti.

this.getCategories().subscribe(categories => {
    this.form.addControl("categoriesFormArr", this.buildCategoryFormArr(categories));
    this.form.addControl("categoriesFormGroup", this.buildCategoryFormGroup(categories));
})

Esistono due approcci per creare l'elenco delle categorie.

1. Form Array

  buildCategoryFormArr(categories: ProductCategory[], selectedCategoryIds: string[] = []): FormArray {
    const controlArr = categories.map(category => {
      let isSelected = selectedCategoryIds.some(id => id === category.id);
      return this.formBuilder.control(isSelected);
    })
    return this.formBuilder.array(controlArr, atLeastOneCheckboxCheckedValidator())
  }
<div *ngFor="let control of categoriesFormArr?.controls; let i = index" class="checkbox">
  <label><input type="checkbox" [formControl]="control" />
    {{ categories[i]?.title }}
  </label>
</div>

Questo buildCategoryFormGroupmi restituirà un FormArray. Accetta anche un elenco di valori selezionati come argomento, quindi se vuoi riutilizzare il modulo per modificare i dati, potrebbe essere utile. Allo scopo di creare un nuovo modulo di prodotto, non è ancora applicabile.

Notato che quando si tenta di accedere ai valori di formArray. Sembrerà [false, true, true]. Per ottenere un elenco di ID selezionati, è necessario un po 'più di lavoro per controllare dall'elenco, ma in base all'indice dell'array. Non mi suona bene ma funziona.

get categoriesFormArraySelectedIds(): string[] {
  return this.categories
  .filter((cat, catIdx) => this.categoriesFormArr.controls.some((control, controlIdx) => catIdx === controlIdx && control.value))
  .map(cat => cat.id);
}

Ecco perché ho pensato di usare FormGroupper quella materia

2. Modulo di gruppo

La differenza del formGroup è che memorizzerà i dati del modulo come oggetto, che richiede una chiave e un controllo del modulo. Quindi è una buona idea impostare la chiave come categoryId e quindi possiamo recuperarla in seguito.

buildCategoryFormGroup(categories: ProductCategory[], selectedCategoryIds: string[] = []): FormGroup {
  let group = this.formBuilder.group({}, {
    validators: atLeastOneCheckboxCheckedValidator()
  });
  categories.forEach(category => {
    let isSelected = selectedCategoryIds.some(id => id === category.id);
    group.addControl(category.id, this.formBuilder.control(isSelected));
  })
  return group;
}
<div *ngFor="let item of categories; let i = index" class="checkbox">
  <label><input type="checkbox" [formControl]="categoriesFormGroup?.controls[item.id]" /> {{ categories[i]?.title }}
  </label>
</div>

Il valore del gruppo del modulo sarà simile a:

{
    "category1": false,
    "category2": true,
    "category3": true,
}

Ma molto spesso vogliamo ottenere solo l'elenco di ID di categoria come ["category2", "category3"]. Devo anche scrivere un get per prendere questi dati. Mi piace questo approccio meglio rispetto al formArray, perché potrei effettivamente prendere il valore dal modulo stesso.

  get categoriesFormGroupSelectedIds(): string[] {
    let ids: string[] = [];
    for (var key in this.categoriesFormGroup.controls) {
      if (this.categoriesFormGroup.controls[key].value) {
        ids.push(key);
      }
      else {
        ids = ids.filter(id => id !== key);
      }
    }
    return ids;
  }

3. È stato selezionato un validatore personalizzato per controllare almeno una casella di controllo

Ho fatto in modo che il validatore controllasse almeno X che fosse selezionata la casella di controllo, per impostazione predefinita controllerà solo una casella di controllo.

export function atLeastOneCheckboxCheckedValidator(minRequired = 1): ValidatorFn {
  return function validate(formGroup: FormGroup) {
    let checked = 0;

    Object.keys(formGroup.controls).forEach(key => {
      const control = formGroup.controls[key];

      if (control.value === true) {
        checked++;
      }
    });

    if (checked < minRequired) {
      return {
        requireCheckboxToBeChecked: true,
      };
    }

    return null;
  };
}

6

Non vedo una soluzione qui che risponda completamente alla domanda utilizzando le forme reattive nella sua massima estensione, quindi ecco la mia soluzione per lo stesso.


Sommario

Ecco il midollo della spiegazione dettagliata insieme a un esempio StackBlitz.

  1. Utilizzare FormArrayper le caselle di controllo e inizializzare il modulo.
  2. L' valueChangesosservabile è perfetto per quando si desidera che il modulo visualizzi qualcosa ma memorizzi qualcos'altro nel componente. Mappa i valori true/ ai falsevalori desiderati qui.
  3. Filtra i falsevalori al momento dell'invio.
  4. Annulla l'iscrizione a valueChangesObservable.

Esempio StackBlitz


Spiegazione dettagliata

Usa FormArray per definire il modulo

Come già accennato nella risposta contrassegnata come corretta. FormArrayè la strada da percorrere nei casi in cui preferiresti ottenere i dati in un array. Quindi la prima cosa che devi fare è creare il modulo.

checkboxGroup: FormGroup;
checkboxes = [{
    name: 'Value 1',
    value: 'value-1'
}, {
    name: 'Value 2',
    value: 'value-2'
}];

this.checkboxGroup = this.fb.group({
    checkboxes: this.fb.array(this.checkboxes.map(x => false))
});

Questo imposterà semplicemente il valore iniziale di tutte le caselle di controllo su false.

Successivamente, è necessario registrare queste variabili del modulo nel modello e iterare checkboxessull'array (NON sui FormArraydati della casella di controllo) per visualizzarle nel modello.

<form [formGroup]="checkboxGroup">
    <ng-container *ngFor="let checkbox of checkboxes; let i = index" formArrayName="checkboxes">
        <input type="checkbox" [formControlName]="i" />{{checkbox.name}}
    </ng-container>
</form>

Usa il valore osservabile

Ecco la parte che non vedo menzionata in nessuna risposta data qui. In situazioni come questa, dove vorremmo visualizzare tali dati ma memorizzarli come qualcos'altro, l' valueChangesosservabile è molto utile. Usando valueChanges, possiamo osservare i cambiamenti nei checkboxese poi mapi valori true/ falsericevuti dai FormArraydati desiderati. Nota che questo non cambierà la selezione delle caselle di controllo poiché qualsiasi valore veritiero passato alla casella di controllo la contrassegnerà come selezionata e viceversa.

subscription: Subscription;

const checkboxControl = (this.checkboxGroup.controls.checkboxes as FormArray);
this.subscription = checkboxControl.valueChanges.subscribe(checkbox => {
    checkboxControl.setValue(
        checkboxControl.value.map((value, i) => value ? this.checkboxes[i].value : false),
        { emitEvent: false }
    );
});

Questo fondamentalmente mappa i FormArrayvalori checkboxessull'array originale e restituisce il valuecaso in cui la casella di controllo è contrassegnata come true, altrimenti ritorna false. Il emitEvent: falseè importante poiché l'impostazione del FormArrayvalore senza causerà valueChangesad emettere un evento creando un ciclo infinito. Impostando emitEventsu false, ci assicuriamo che l' valueChangesosservabile non venga emesso quando impostiamo il valore qui.

Filtra i falsi valori

Non possiamo filtrare direttamente i falsevalori in FormArrayperché così facendo si rovinerà il modello poiché sono legati alle caselle di controllo. Quindi la migliore soluzione possibile è filtrare i falsevalori durante l'invio. Usa l'operatore spread per farlo.

submit() {
    const checkboxControl = (this.checkboxGroup.controls.checkboxes as FormArray);
    const formValue = {
        ...this.checkboxGroup.value,
        checkboxes: checkboxControl.value.filter(value => !!value)
    }
    // Submit formValue here instead of this.checkboxGroup.value as it contains the filtered data
}

Questo fondamentalmente filtra i valori falsi dal file checkboxes.

Annulla l'iscrizione a valueChanges

Infine, non dimenticare di annullare l'iscrizione a valueChanges

ngOnDestroy() {
    this.subscription.unsubscribe();
}

Nota: esiste un caso speciale in cui un valore non può essere impostato su FormArrayin valueChanges, ovvero se il valore della casella di controllo è impostato sul numero 0. Questo farà sembrare che la casella di controllo non possa essere selezionata poiché la selezione della casella di controllo imposterà FormControlcome numero 0(un valore falso) e quindi la manterrà deselezionata. Sarebbe preferibile non utilizzare il numero 0come valore, ma se è richiesto, è necessario impostarlo in modo condizionale 0su un valore veritiero, ad esempio stringa '0'o semplicemente semplice truee quindi, dopo l'invio, convertirlo di nuovo nel numero 0.

Esempio StackBlitz

StackBlitz ha anche il codice per quando si desidera passare i valori predefiniti alle caselle di controllo in modo che vengano contrassegnate come selezionate nell'interfaccia utente.


4

Crea un evento quando viene cliccato e quindi modifica manualmente il valore di true con il nome di ciò che rappresenta la casella di controllo, quindi il nome o true valuterà lo stesso e puoi ottenere tutti i valori invece di un elenco di true / false. Ex:

component.html

<form [formGroup]="customForm" (ngSubmit)="onSubmit()">
    <div class="form-group" *ngFor="let parameter of parameters"> <!--I iterate here to list all my checkboxes -->
        <label class="control-label" for="{{parameter.Title}}"> {{parameter.Title}} </label>
            <div class="checkbox">
              <input
                  type="checkbox"
                  id="{{parameter.Title}}"
                  formControlName="{{parameter.Title}}"
                  (change)="onCheckboxChange($event)"
                  > <!-- ^^THIS^^ is the important part -->
             </div>
      </div>
 </form>

component.ts

onCheckboxChange(event) {
    //We want to get back what the name of the checkbox represents, so I'm intercepting the event and
    //manually changing the value from true to the name of what is being checked.

    //check if the value is true first, if it is then change it to the name of the value
    //this way when it's set to false it will skip over this and make it false, thus unchecking
    //the box
    if(this.customForm.get(event.target.id).value) {
        this.customForm.patchValue({[event.target.id] : event.target.id}); //make sure to have the square brackets
    }
}

Questo cattura l'evento dopo che è già stato cambiato in vero o falso da Angular Forms, se è vero cambio il nome con il nome di ciò che rappresenta la casella di controllo, che se necessario valuterà anche come vero se viene controllato vero / falso come bene.


Questo mi ha portato sulla strada giusta, ho finito per fare this.customForm.patchValue ({[event.target.id]: event.target.checked});
Demodave

4

Se desideri utilizzare una forma reattiva angolare ( https://angular.io/guide/reactive-forms ).

È possibile utilizzare un controllo modulo per gestire il valore emesso dal gruppo di caselle di controllo.

componente

import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import { flow } from 'lodash';
import { flatMap, filter } from 'lodash/fp';

@Component({
  selector: 'multi-checkbox',
  templateUrl: './multi-checkbox.layout.html',
})
export class MultiChecboxComponent  {

  checklistState = [ 
      {
        label: 'Frodo Baggins',
        value: 'frodo_baggins',
        checked: false
      },
      {
        label: 'Samwise Gamgee',
        value: 'samwise_gamgee',
        checked: true,
      },
      {
        label: 'Merry Brandybuck',
        value: 'merry_brandybuck',
        checked: false
      }
    ];

  form = new FormGroup({
    checklist : new FormControl(this.flattenValues(this.checklistState)),
  });


  checklist = this.form.get('checklist');

  onChecklistChange(checked, checkbox) {
    checkbox.checked = checked;
    this.checklist.setValue(this.flattenValues(this.checklistState));
  }

  flattenValues(checkboxes) {
    const flattenedValues = flow([
      filter(checkbox => checkbox.checked),
      flatMap(checkbox => checkbox.value )
    ])(checkboxes)
    return flattenedValues.join(',');
  }
}

html

<form [formGroup]="form">
    <label *ngFor="let checkbox of checklistState" class="checkbox-control">
    <input type="checkbox" (change)="onChecklistChange($event.target.checked, checkbox)" [checked]="checkbox.checked" [value]="checkbox.value" /> {{ checkbox.label }}
  </label>
</form>

checklistState

Gestisce il modello / stato degli input della checklist. Questo modello ti consente di mappare lo stato corrente su qualsiasi formato di valore di cui hai bisogno.

Modello:

{
   label: 'Value 1',
   value: 'value_1',
   checked: false
},
{
  label: 'Samwise Gamgee',
  value: 'samwise_gamgee',
  checked: true,
},
{
  label: 'Merry Brandybuck',
  value: 'merry_brandybuck',
  checked: false
}

checklist Controllo del modulo

Questo controllo memorizza il valore che si desidera salvare come es

valore di output: "value_1,value_2"

Guarda la demo su https://stackblitz.com/edit/angular-multi-checklist


Facilmente la migliore soluzione per me. Grazie mille.
Newclique

2

La mia soluzione: risolto per Angular 5 con Material View
La connessione è tramite

formArrayName = "notifica"

(change) = "updateChkbxArray (n.id, $ event.checked, 'notification')"

In questo modo può funzionare per più array di caselle di controllo in una forma. Basta impostare il nome della matrice di controlli per connettersi ogni volta.

constructor(
  private fb: FormBuilder,
  private http: Http,
  private codeTableService: CodeTablesService) {

  this.codeTableService.getnotifications().subscribe(response => {
      this.notifications = response;
    })
    ...
}


createForm() {
  this.form = this.fb.group({
    notification: this.fb.array([])...
  });
}

ngOnInit() {
  this.createForm();
}

updateChkbxArray(id, isChecked, key) {
  const chkArray = < FormArray > this.form.get(key);
  if (isChecked) {
    chkArray.push(new FormControl(id));
  } else {
    let idx = chkArray.controls.findIndex(x => x.value == id);
    chkArray.removeAt(idx);
  }
}
<div class="col-md-12">
  <section class="checkbox-section text-center" *ngIf="notifications  && notifications.length > 0">
    <label class="example-margin">Notifications to send:</label>
    <p *ngFor="let n of notifications; let i = index" formArrayName="notification">
      <mat-checkbox class="checkbox-margin" (change)="updateChkbxArray(n.id, $event.checked, 'notification')" value="n.id">{{n.description}}</mat-checkbox>
    </p>
  </section>
</div>

Alla fine stai arrivando a salvare il modulo con un array di ID record originali da salvare / aggiornare. La vista dell'interfaccia utente

La parte rilevante del json del modulo

Sarò felice di avere commenti per il miglioramento.


0

PARTE DEL MODELLO: -

    <div class="form-group">
         <label for="options">Options:</label>
         <div *ngFor="let option of options">
            <label>
                <input type="checkbox"
                   name="options"
                   value="{{option.value}}"
                   [(ngModel)]="option.checked"
                                />
                  {{option.name}}
                  </label>
              </div>
              <br/>
         <button (click)="getselectedOptions()"  >Get Selected Items</button>
     </div>

PARTE CONTROLLORE: -

        export class Angular2NgFor {

          constructor() {
             this.options = [
              {name:'OptionA', value:'first_opt', checked:true},
              {name:'OptionB', value:'second_opt', checked:false},
              {name:'OptionC', value:'third_opt', checked:true}
             ];


             this.getselectedOptions = function() {
               alert(this.options
                  .filter(opt => opt.checked)
                  .map(opt => opt.value));
                }
             }

        }

1
Ciao @EchoLogic .. Per favore fatemi sapere in caso di qualsiasi domanda
Abhishek Srivastava

1
Questo non sta usando ReactiveForms ma forme regolari, quindi non risponde alla domanda
Guillaume

0

Aggiungi i miei 5 centesimi) Il mio modello di domanda

{
   name: "what_is_it",
   options:[
     {
      label: 'Option name',
      value: '1'
     },
     {
      label: 'Option name 2',
      value: '2'
     }
   ]
}

template.html

<div class="question"  formGroupName="{{ question.name }}">
<div *ngFor="let opt of question.options; index as i" class="question__answer" >
  <input 
    type="checkbox" id="{{question.name}}_{{i}}"
    [name]="question.name" class="hidden question__input" 
    [value]="opt.value" 
    [formControlName]="opt.label"
   >
  <label for="{{question.name}}_{{i}}" class="question__label question__label_checkbox">
      {{opt.label}}
  </label>
</div>

component.ts

 onSubmit() {
    let formModel = {};
    for (let key in this.form.value) {
      if (typeof this.form.value[key] !== 'object') { 
        formModel[key] = this.form.value[key]
      } else { //if formgroup item
        formModel[key] = '';
        for (let k in this.form.value[key]) {
          if (this.form.value[key][k])
            formModel[key] = formModel[key] + k + ';'; //create string with ';' separators like 'a;b;c'
        }
      }
    }
     console.log(formModel)
   }

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.