2017-04-24 115 views
8

我不確定綁定和更新複選框動態生成模型的正確方法。 (這是一個最初使用Yeoman生成器創建的Angular 2的ASP.NET Core項目)或者我剛剛發現的一個簡單的複選框。將ngModel綁定到動態複選框列表:Angular 2/Typescript

下面是精簡代碼,它有一個設施和時隙。每個設施可以有多個時隙。時間段複選框列表顯示正常。初始數據表示只應檢查一個時隙。但是當我加載一個設施時,所有的時隙都會被檢查。他們沒有像我期望的那樣與ngModel綁定。

  1. 如何解決呢所以只能包含在設施的數據時隙進行檢查,而不是全部?
  2. 如何將檢查的內容綁定到ngModel時隙屬性?我是否需要在組件上創建數組屬性並操作它,而不是依賴ngModel? (嘗試過,但顯然沒有這樣做,因此恢復到下面的代碼)
  3. 我似乎也有一個問題綁定到一個簡單的複選框(haselectric),因爲這也不是檢查時,它應該是。我是否錯過了可以解決所有這些問題的導入?

代碼說明 我有兩個對象(設施和時隙)來自我綁定到接口的api。他們在性能已經顯著下降爲簡單起見:

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

}

P.S.我在設施對象中有兩個屬性用於時間段的原因是因爲ID列表更容易通過API進行更新。而不是傳遞完整的模型(時隙大於我在這裏,不需要更新數據庫)。請保留評論,因爲它與需要完成的內容無關。

我發現這個問題...但遺憾的是,沒有人回答了這個可憐的傢伙:ngmodel binding with dynamic array of checkbox in angular2 試過,但沒有奏效:Get values from a dynamic checkbox list 我也嘗試更新的複選框(變化)的本地屬性的版本,但是這似乎並沒有工作,要麼:Angular 2: Get Values of Multiple Checked Checkboxes

回答

8

根據上面的НЛО答案我能夠找出解決我的問題。謝謝НЛО。

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

我有一個類似於你的代碼(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由於材料。這種笨拙的解決方案,但我認爲它會幫助你弄清楚你怎麼能達到你想要的東西

+0

謝謝了。去嘗試一下並回傳。 – EHeine

+0

這指出了我需要的方向。我用解決方案代碼更新了我的原始帖子。非常感謝你! – EHeine

+2

@Eeeine很高興你明白了。你應該發佈工作解決方案作爲答案,並接受它,雖然 –