web-dev-qa-db-fra.com

Liaison de ngModel à la liste de cases à cocher dynamiques: Angular 2 / Typescript

Je ne suis pas sûr de la bonne façon de lier et de mettre à jour un modèle où les cases à cocher sont générées dynamiquement. (Il s'agit d'un projet ASP.NET Core avec Angular 2 initialement créé à l'aide du générateur Yeoman) Ou une simple case à cocher d'ailleurs que je viens de découvrir.

Ci-dessous, le code dépouillé, qui a une installation et des plages horaires. Chaque établissement peut avoir plusieurs plages horaires. La liste des cases de créneau horaire s'affiche correctement. Les données initiales indiquent qu'un seul intervalle de temps doit être vérifié. Mais lorsque je charge une installation, tous les intervalles de temps sont vérifiés. Ils ne sont pas liés avec ngModel comme je m'y attendais.

  1. Comment puis-je résoudre ce problème afin que seuls les intervalles de temps inclus dans les données de l'installation soient vérifiés plutôt que tous?
  2. Comment lier ce qui est vérifié à la propriété ngModel timeslotids? Dois-je créer une propriété de tableau sur le composant et la manipuler au lieu de compter sur ngModel? (a essayé cela mais évidemment ne l'a pas fait correctement, donc je suis revenu au code ci-dessous)
  3. Il me semble également que j'ai un problème lié à une simple case à cocher (haselectric) car cela ne coche pas non plus quand il devrait l'être. Suis-je en train de manquer une importation qui réglerait tout cela ??

EXPLICATION DU CODE J'ai deux objets (facilité et intervalle de temps) provenant d'une API que je lie à des interfaces. Pour des raisons de simplicité, leur propriétés ont été considérablement réduites:

export interface IFacility {   
   id: number,
   name: string,
   haselectric: boolean, 
   timeslotids: number[],    
   timeslots: ITimeslot[]

}
export interface ITimeslot {
    id: number,
    timeslotname: string    
}

Ce sont les données JSON pour Timeslots:

[{"id":1,"timeslotname":"Daily"},{"id":2,"timeslotname":"Hourly"},{"id":4,"timeslotname":"Market"}]

Il s'agit des données JSON pour une seule installation avant d'être mises à jour:

{"id":2,"name":"Clements Building","haselectric":true,"timeslotids":[1],"timeslots":[{"id":1,"timeslotname":"Daily"}]}

Composant pour l'édition d'une installation (facility.component.html):

<form #form="ngForm" (ngSubmit)="submitForm()" *ngIf="formactive">
   <input type="hidden" [(ngModel)]="updatedfacility.id" #id="ngModel" name="id" />
    <div class="form-group">
         <label for="name">Facility Name *</label>
         <input type="text" class="form-control input-lg" [(ngModel)]="updatedfacility.name" #name="ngModel" name="name" placeholder="Facility Name *">
   </div>
   <div class="form-group">
                    <label for="exhibitspaces">Has Electric *</label>
                    <input type="checkbox" class="form-control input-lg" [(ngModel)]="updatedfacility.haselecric" #haselectric="ngModel" name="haselectric">
    </div>
    <div class="form-group">
        <label for="timeslots">Select Timeslots Available for Rent *</label>
        <div *ngIf="dbtimeslots" >
            <span *ngFor="let timeslot of dbtimeslots" class="checkbox">
                <label for="timeslot">
                    <input type="checkbox" [(ngModel)]="updatedfacility.timeslotids" value="{{timeslot.id}}" name="{{timeslot.id}}" [checked]="updatedfacility.timeslotids.indexOf(timeslot.id)" />{{timeslot.timeslotname}}
                 </label>
             </span>
        </div>
    </div>
    <button type="submit" class="btn btn-lg btn-default" [disabled]="form.invalid">Update</button> 
</form>

Code du composant (facility.component.ts)

import { Component, OnInit, Input, Output, OnChanges, EventEmitter  } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { ActivatedRoute, Router } from '@angular/router'; 
import { FormsModule }  from '@angular/forms';
import { FacilityService }  from '../../../services/facility.service';
import { TimeslotService } from '../../../services/timeslot.service';
import { IFacility } from '../../../services/facility.interface';
import { ITimeslot } from '../../../services/timeslot.interface';

@Component({
   template: require('./facility.component.html')
})
export class FacilityDetailsComponent {
  facility: IFacility;
  httpresponse: string;
  successMessage: string;
  errormessage: string;
  showSuccess: boolean = true;
  showError: boolean = true;
  formactive: boolean = true;
  dbtimeslots: ITimeslot[];    


  constructor(
    private _route: ActivatedRoute,
    private _router: Router,
    private _facilityservice: FacilityService,
    private _timeslotservice: TimeslotService
  ) {}

  ngOnInit(): void {
    this._timeslotservice.getTimeslots().subscribe(timeslots => this.dbtimeslots = timeslots, error => this.errormessage = <any>error);
    let id = +this._route.snapshot.params['id'];

    this._facilityservice.getFacility(id)
        .subscribe(facility => this.facility = facility,
        error => this.errormessage = <any>error);

  }

  submitForm() {
    //update the facility through the service call
    this._facilityservice.updateFacility(this.facility)
        .subscribe(response => {
            this.httpresponse = response;
            console.log(this.httpresponse);
            this.successMessage = "Facility updated!";
            this.formactive = false;
            setTimeout(() => this.formactive = true, 3);
            this.showSuccess = false;
        },
        error => {
            this.errormessage = <any>error;
            this.showError = false;
        });
  }     

}

P.S. La raison pour laquelle j'ai deux propriétés dans l'objet installation pour les intervalles de temps est parce qu'une liste d'ID est beaucoup plus facile à transmettre à l'API pour la mise à jour. Plutôt que de passer des modèles complets (les intervalles de temps sont plus grands que ce que j'ai ici et ne sont pas nécessaires pour mettre à jour la base de données). Veuillez réserver des commentaires à ce sujet car cela n'a aucun rapport avec ce qui doit être accompli.

J'ai trouvé cette question ... mais malheureusement, personne n'a répondu à ce pauvre gars: liaison ngmodel avec tableau dynamique de case à cocher dans angular2 J'ai essayé cela mais n'a pas fonctionné: Obtenez les valeurs d'une dynamique checkbox list J'ai également essayé la version de mise à jour d'une propriété locale sur (changer) de la case à cocher mais cela ne semble pas fonctionner non plus: Angular 2: Get Values ​​of Multiple Checked Checkboxes

9
EHeine

Sur la base de la réponse de НЛО ci-dessus, j'ai pu trouver la solution à ma question. Merci НЛО.

<div class="form-group">
    <label for="timeslots">Select Timeslots Available for Rent *</label>
    <div *ngIf="dbtimeslots">
        <span *ngFor="let timeslot of dbtimeslots" class="checkbox">
            <label>
                <input type="checkbox" value="{{timeslot.id}}" name="{{timeslot.id}}"  [checked]="(facility.timeslotids && (-1 !== facility.timeslotids.indexOf(timeslot.id)) ? 'checked' : '')" (change) ="updateSelectedTimeslots($event)" />{{timeslot.timeslotname}}
            </label>
         </span>
    </div>
</div>

Ensuite, la fonction sur le composant:

updateSelectedTimeslots(event) {
    if (event.target.checked) {
          if (this.facility.timeslotids.indexOf(parseInt(event.target.name)) < 0) { 
                this.facility.timeslotids.Push(parseInt(event.target.name));

          }
     } else {
           if (this.facility.timeslotids.indexOf(parseInt(event.target.name)) > -1) 
            {
                this.facility.timeslotids.splice(this.facility.timeslotids.indexOf(parseInt(event.target.name)), 1);              
            }
    }
     //console.log("TimeslotIDs: ", this.facility.timeslotids);    
}
14
EHeine

J'ai un code similaire au vôtre (ngFor sur toutes les cases à cocher possibles, certaines doivent être vérifiées, les modifications doivent être enregistrées dans une structure de données sur laquelle nous ne répétons pas), et voici ce que je propose avec:

<md-checkbox 
    *ngFor="let some of availableSomes"
    name="{{ some }}"
    checked="{{ data.somes && -1 !== this.data.somes.indexOf(some) ? 'checked' : '' }}"
    (change)="updateSome($event)">
    {{ some }}
</md-checkbox>

Voici updateSome:

updateSome(event) {
  if (-1 !== this.availableSkills.indexOf(event.source.name)) {
    if (event.checked) {
      this.data.somes.Push(event.source.name);
    } else {
      this.data.somes.splice(this.data.somes.indexOf(event.source.name), 1);
    }
  }
}

En outre, je pense que cela devrait être event.target, mais c'est event.source en raison du matériau. Type de solution maladroite, mais je pense que cela vous aidera à comprendre comment pouvez-vous réaliser ce que vous voulez

11
НЛО