将ngModel绑定到动态复选框列表:Angular 2/Typescript [英] Binding ngModel to Dynamic Checkbox List : Angular 2 / Typescript
问题描述
我不确定绑定和更新动态生成复选框的模型的正确方法. (这是一个最初使用Yeoman生成器创建的Angular 2的ASP.NET Core项目),或者我刚刚发现的一个简单复选框.
I'm not sure the proper way to bind and update a model where the checkboxes are dynamically generated. (This is a ASP.NET Core project with Angular 2 initially created using the Yeoman generator) Or a simple checkbox for that matter I have just found out.
下面是精简的代码,其中包含一个功能和时隙.每个设施可以具有多个时隙.时间段复选框列表显示正常.初始数据指示仅应检查一个时隙.但是,当我加载设施时,将检查所有时隙.他们没有像我预期的那样与ngModel绑定.
Below is stripped down code, which has a facility and timeslots. Each facility can have multiple timeslots. The timeslot checkbox list displays fine. The initial data indicates only one timeslot should be checked. But when I load up a facility, all the timeslots are checked. They aren't binding with ngModel as I expected.
- 如何解决它,以便仅检查设施数据中包括的时隙而不是全部?
- 如何将检查的内容绑定到ngModel timeslotids属性?我是否需要在组件上创建一个数组属性并对其进行操作,而不是依赖于ngModel? (尝试过此操作,但显然没有正确执行,因此恢复为下面的代码)
- 我似乎在绑定到一个简单的复选框(haselectric)时也遇到了问题,因为这也没有在应有的时间进行检查.我错过了可以解决所有问题的导入吗?
代码说明 我有两个对象(功能和时间段)来自我绑定到接口的api.为了简单起见,它们的属性已大大降低:
CODE EXPLANATION I have two objects (facility and timeslot) coming from an api which I bind to interfaces. They have been significantly reduced in properties for simplicity's sake:
export interface IFacility {
id: number,
name: string,
haselectric: boolean,
timeslotids: number[],
timeslots: ITimeslot[]
}
export interface ITimeslot {
id: number,
timeslotname: string
}
这是时间段的JSON数据:
This is the JSON data for Timeslots:
[{"id":1,"timeslotname":"Daily"},{"id":2,"timeslotname":"Hourly"},{"id":4,"timeslotname":"Market"}]
这是在更新之前单个设施的JSON数据:
This is the JSON data for a single Facility prior to being updated:
{"id":2,"name":"Clements Building","haselectric":true,"timeslotids":[1],"timeslots":[{"id":1,"timeslotname":"Daily"}]}
用于编辑设施的组件(facility.component.html):
Component for editing a facility (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)
Code for the component (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进行更新.而不是传递完整的模型(时隙比我在这里使用的要大,并且不需要更新数据库).请保留对此的评论,因为它与需要完成的任务无关.
P.S. The reason I have a two properties in the facility object for timeslots is because a list of id's is much easier to pass through to the API for updating. Rather than passing full models (timeslots is larger than what I have here and not needed to update the database). Please reserve comments on that as it's unrelated to what needs to be accomplished.
我发现了这个问题...但是可悲的是,没有人回答这个可怜的家伙:从动态复选框列表中获取值 我还尝试了在复选框的(更改)上更新本地属性的版本,但这似乎也不起作用:
I found this question...but sadly, no one answered this poor fellow: ngmodel binding with dynamic array of checkbox in angular2 Tried this but didn't work: Get values from a dynamic checkbox list I also tried version of updating an local property on (change) of the checkbox but that didn't seem to work either: Angular 2: Get Values of Multiple Checked Checkboxes
推荐答案
基于上面的НЛО答案,我能够找出问题的解决方案.谢谢НЛО.
Based on НЛО answer above I was able to figure out the solution to my question. Thank you НЛО.
<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>
然后在组件上执行该功能:
Then the function on the component:
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);
}
这篇关于将ngModel绑定到动态复选框列表:Angular 2/Typescript的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!