web-dev-qa-db-ja.com

ngModelを動的チェックボックスリストにバインド:Angular 2 / Typescript

チェックボックスが動的に生成されるモデルをバインドおよび更新する適切な方法がわかりません。 (これは、最初にYeomanジェネレーターを使用して作成されたAngular 2)のASP.NET Coreプロジェクトです)または、私が見つけた問題に関する単純なチェックボックスです。

以下は、機能とタイムスロットを備えた簡略化されたコードです。各施設には複数のタイムスロットを設定できます。タイムスロットチェックボックスリストは正常に表示されます。初期データは、1つのタイムスロットのみをチェックする必要があることを示しています。しかし、施設をロードすると、すべてのタイムスロットがチェックされます。彼らは私が期待したようにngModelとバインドしていません。

  1. 施設データに含まれるタイムスロットのみがすべてではなくチェックされるように修正するにはどうすればよいですか?
  2. チェックされているものをngModel timeslotidsプロパティにバインドするにはどうすればよいですか?コンポーネントに配列プロパティを作成し、ngModelに依存する代わりにそれを操作する必要がありますか? (これを試しましたが、明らかに正しくしませんでしたので、以下のコードに戻りました)
  3. 私はまた、単純なチェックボックス(haselectric)にバインドする問題を抱えているようです。これをすべて修正するインポートがありませんか?

コードの説明インターフェイスにバインドするAPIからの2つのオブジェクト(ファシリティとタイムスロット)があります。単純化のために、プロパティが大幅に削減されています。

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

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

これはタイムスロットのJSONデータです。

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

これは、更新される前の単一の施設のJSONデータです。

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

施設を編集するためのコンポーネント(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>

コンポーネントのコード(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;
        });
  }     

}

追伸タイムスロットの機能オブジェクトに2つのプロパティがあるのは、更新のためにIDのリストをAPIに渡すのがはるかに簡単だからです。完全なモデルを渡すのではなく(タイムスロットはここにあるものよりも大きく、データベースを更新する必要はありません)。達成する必要があることとは無関係であるため、コメントを控えてください。

私はこの質問を見つけました...しかし、悲しいことに、誰もこの貧しい仲間に答えませんでした: ng2とangular2のチェックボックスの動的配列とのバインディング これを試してみましたが、動作しませんでした: 動的チェックボックスリストから値を取得する チェックボックスの(変更)でローカルプロパティを更新するバージョンも試しましたが、どちらも機能していないようです: Angular 2 :複数のチェックされたチェックボックスの値を取得する

9
EHeine

上記のНЛОの回答に基づいて、私は私の質問の解決策を見つけ出すことができました。 НЛОありがとうございます。

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

次に、コンポーネントの関数:

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

私はあなたのものに似たコードを持っています(可能なチェックボックスすべてにngFor、それらのいくつかをチェックする必要があり、変更は反復していないデータ構造に保存する必要があります)、ここに私が出てくるものがありますで:

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

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

また、event.target、ただしevent.source材料による。ちょっと不器用なソリューションですが、どうすれば目的を達成できるかを理解するのに役立つと思います

11
НЛО