我正在创建一个带有复选框(多个选项)字段的表单 我将在我的应用程序中的许多地方使用这种类型的字段,这就是为什么我决定使用指令来实现此功能。
我注意到Angular2不是很好地支持复选框(多个选项)
因此我使用[checked]
选项来复选框以验证复选框是否已选中,(change)
更新我的模型。
在开发过程中,我注意到单击复选框时,[checked]
会多次触发,并且还会检查所有选项,而不仅仅是我点击的选项。
我创建了一个plunkr来向您展示我正在谈论的内容。
我想知道为什么[checked]
多次触发(在这个plunkr中两次)并且它检查所有选项而不仅仅是点击的那个?
答案 0 :(得分:1)
Angular是如何运作的。您更改了应用程序模型的某些部分,Angular正在检查"区域"模型所在的位置(它更复杂,你应该在Angular中搜索区域)。
http://blog.thoughtram.io/angular/2016/02/01/zones-in-angular-2.html
http://blog.thoughtram.io/angular/2016/01/22/understanding-zones.html
答案 1 :(得分:1)
[checked]
或类似的异步调用),Angular2s更改检测都会调用 setTimeout
,以确定每个选项的checked
属性是否为const timeToWait : number = 500;
const keyDigitsUp$ = Observable.fromEvent(document, "keyup")
.filter((event:any) => {return ((event.keyCode>=48 && event.keyCode <=57) ||
(event.keyCode>=96 && event.keyCode <=106))});
let bufferedEvents = Observable.from(keyDigitsUp$).bufferCount(2);
let numbers : string = "";
bufferedEvents.subscribe((eventArray) => {
if (eventArray[1].timeStamp - eventArray[0].timeStamp <= timeToWait)
{
numbers+=eventArray[0].key + eventArray[1].key;
}
else
{
numbers="";
}
});
属性。项目需要更新。
答案 2 :(得分:1)
我在angular2中创建了Multicheckbox组件。请检查Plunker网址:Plunker Here
请在您的应用程序中导入此组件,并多次使用它。
1)multicheckbox.ts
import {Component, Input, Output, EventEmitter, OnInit, OnChanges, ChangeDetectionStrategy} from '@angular/core';
import {Pipe, PipeTransform} from "@angular/core";
declare var $:any;
//var chkSelectedArr=[];
/**
* Define input data interface
*/
export interface chkArrayInterface {
id: string;
title: string;
}
/**
* checked checkbox to array
*/
@Pipe({ name: 'chkChecked', pure: false })
export class ChkChecked implements PipeTransform {
transform(value, args): any {
if(args !== undefined && args.length !== 0){
if(args.includes(value)){
return true;
}else{
return false;
}
}
}
}
/**
* filter checkbox list
*/
@Pipe({ name: 'filter', pure: true })
export class FilterPipe{
transform(items: any[], args: any): any {
let filter = args.toString();
if(filter !== undefined && filter.length !== null){
if(filter.length === 0 || items.length ===0){
return items;
}else{
return filter ? items.filter(item=> item.title.toLocaleLowerCase().indexOf(filter) != -1) : items;
}
}
}
}
/**
* Multi select checkbox component
*/
@Component({
selector: 'multi-checkbox',
pipes: [FilterPipe, ChkChecked],
//changeDetection: ChangeDetectionStrategy.OnPush,
template : `
<div class="custom-multicheck-box">
<div class="input-group custom-search-box" *ngIf="isFilter">
<div class="input-group-addon">
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
</div>
<input type="text" class="form-control" (keyup)="changeFilter()" (input)="txtSearch = $event.target.value" [value]="txtSearch" [placeholder]="filterTitle" />
<div class="input-group-addon" (click)="resetSearch()">
<span class="glyphicon glyphicon-remove-sign" aria-hidden="true"></span>
</div>
</div>
<div class="custom-list-box" [style.height]="height">
<input type="checkbox" [checked]="isSelectAll" (change)="selectAll($event)" />
<span class="select-all">Select All</span>
<ul>
<li *ngFor="let chk of chkArray | filter:txtSearch">
<input type="checkbox" [checked]="chk.id | chkChecked: chkSelected " (change)="selectChk($event,chk.id)" />
<span>{{chk?.title}}</span>
</li>
</ul>
</div>
</div>
`,
styles: [`
.custom-multicheck-box {
border: 1px solid rgba(0,0,0,.15);
border-radius: .25rem;
padding: 5px 0;
left: 10px;
overflow: hidden;
position: reletive
}
.custom-list-box {
margin: 10px 0px 10px 10px;
color: #0082c6;
overflow-y: auto;
}
.custom-search-box {
margin: 7px;
}
li {
padding-top: 3px;
font-weight: 400;
font-size: .8125rem;
}
li > span {
margin-left:10px;
}
span.select-all {
margin-left:10px;
font-weight: bold;
font-size: .8125rem;
}
.input-group-addon .glyphicon-remove-sign {
cursor: pointer;
}
`]
})
export class MultiCheckboxComponent implements OnInit, OnChanges {
@Input() chkArray: chkArrayInterface[]=[];
@Input() chkSelected: Array<any>=[];
@Input() filterTitle: string="Filter";
@Input() isFilter: boolean=true;
@Input() height: string="100px";
@Output() chkResult: EventEmitter<any> = new EventEmitter();
private txtSearch:string="";
private chkSelectedArr:any[]=[];
private isSelectAll:boolean;
private fiteredArr:any;
private filterPipe:any;
constructor() {
this.isSelectAllCheckbox();
}
ngOnInit() {
}
ngOnChanges(){
this.isSelectAllCheckbox();
}
/**
* Checked is selectAll or not
*/
isSelectAllCheckbox(){
if(this.chkArray !== undefined && this.chkArray !== null
&& this.chkSelected !== undefined && this.chkSelected!==null){
if(this.chkArray.length === this.chkSelected.length && this.chkArray.length !==0){
this.isSelectAll = true;
}else{
this.isSelectAll = false;
}
}
}
/**
* Select all then all checkbox selected
*/
selectAll(event) {
event.preventDefault();
this.filterPipe = new FilterPipe();
this.fiteredArr = this.filterPipe.transform(this.chkArray,this.txtSearch);
this.chkSelected = [];
this.isSelectAll = event.target.checked;
if(this.fiteredArr !== undefined && event.target.checked === true && this.fiteredArr.length !==0){
this.fiteredArr.forEach(chk => {
this.chkSelected.push(chk.id);
});
}
this.chkResult.emit({
value: this.chkSelected
})
}
/**
* Select perticular checkbox
*/
selectChk(event, val){
if(event.target.checked === true){
this.chkSelected.push(val);
}else{
var index = this.chkSelected.indexOf(val);
this.chkSelected.splice(index, 1);
}
this.isSelectAllCheckbox();
this.chkResult.emit({
value: this.chkSelected
})
}
/**
* Reset filter checkbox
*/
resetSearch(){
this.txtSearch="";
this.changeFilter();
}
/**
* Check on filter selected all or not
*/
changeFilter(){
this.filterPipe = new FilterPipe();
this.fiteredArr = this.filterPipe.transform(this.chkArray,this.txtSearch);
if(this.fiteredArr !== undefined && this.chkSelected !== undefined){
if(this.fiteredArr.length === this.chkSelected.length && this.fiteredArr.length !== 0){
this.isSelectAll = true;
}else{
this.isSelectAll = false;
}
}
}
}