Angular 2-复选框未保持同步 [英] Angular 2 - Checkbox not kept in sync
问题描述
我正在使用Angular 2.0(是的,比当前的2.4落后了一点).
Im working on Angular 2.0 (Yes, a bit behind from current 2.4).
我有一个复选框列表. 我要确保在未选中最后一个复选框"的情况下,所有复选框均已选中.
I have a checkbox list. Im trying to make that when the LAST CHECKBOX IS UNCHECKED all CHECKBOXES ARE CHECKED.
HTML
<div *ngFor="let filter of filters">
<label htmlFor="check-box-{{filter.text}}"
[ngClass]="(filter.selected)? 'active' : '' ">
<input type="checkbox"
name="check-box-{{filter.text}}"
[checked]="filter.selected"
(change)="onSelectFilter(filter)"
attr.id="check-box-{{filter.text}}">
{{filter.selected}} - ({{filter.counter}})
</label>
</div>
TS
onSelectFilter(filter: Filter){
filter.toggleSelection();
let isAnyFilterSelected = this.filters.find(filter => filter.selected);
// If no filter is selected then ALL filters are selected
if(!isAnyFilterSelected){
this.filters.forEach(filter => filter.selected = true );
}
}
我为此制造了一个塞子.
I create a plunker for it.
https://plnkr.co/edit/uzF6Lk5fxRZjXBOaS9ob?p=preview
如果取消选中唯一具有CHECKED属性为TRUE的复选框,则我希望所有复选框都具有CHECKED属性.这不会发生.
If unchecked the only checkbox with CHECKED attribute TRUE, Im expecting that ALL checkboxes would have CHECKED attribute. This does not happen.
有什么想法吗?
推荐答案
您应该使用ngModel
而不是绑定到checked
,并使用setTimeout
.
You should use ngModel
instead of binding to checked
, and use a setTimeout
.
<div *ngFor="let filter of filters">
<label htmlFor="check-box-{{filter.text}}"
[ngClass]="(filter.selected)? 'active' : '' ">
<input type="checkbox"
name="check-box-{{filter.text}}"
[ngModel]="filter.selected"
(ngModelChange)="onSelectFilter($event,filter)"
attr.id="check-box-{{filter.text}}">
{{filter.selected}} - ({{filter.counter}})
</label>
</div>
onSelectFilter(selected:boolean,filter: Filter){
filter.selected=selected;
if(this.filters.every(filter=>!filter.selected)){
setTimeout(()=>{
this.filters.forEach(filter=>filter.selected=true);
});
}
}
实际上,因为从变更检测器的角度来看,以前的状态与新的状态之间没有变化.
Actually, because from change-detector's point of view, there is no change between the previous state and the new one.
因此无需更新子级的@Input()
/调用).
So there is no need to update the @Input()
of the child /call the writeValue()
method of the ControlValueAccessor
(<input type="checkbox" [ngModel]="foo">
).
使用setTimeout,首先将属性更新为false,然后将其更改延迟回到初始状态,从而允许进行新的更改检测周期.
Using setTimeout, you first update the property to false, then delay its change back to initial state, allowing a new change-detection cycle.
还要注意,像(ngModelChange)
这样的事件与变更检测周期无关.
Also note that events like (ngModelChange)
are not correlated to the change-detection cycle.
在这里,我们将得到与您的示例相同的结果,尽管我们将foo
设置为true,但复选框不会更新:
Here, we will get the same result as in your example, while we keep foo
being true, the checkbox won't update :
@Component({
selector: 'my-app',
template: `
<input id="foo" type="checkbox" [ngModel]="foo" (ngModelChange)="fooChange($event)"><label for="foo">{{foo}}</label>
`,
})
export class App {
filters:[];
foo=true
fooChange(newValue:boolean){
if(newValue===false)
this.foo=true; // if newValue is false, foo becomes true
else
this.foo = newValue; // otherwise, do change
}
}
内幕发生了什么:
这次,我们将延迟使用setTimeout
将值重置为下一个刻度:
This time we will delay resetting the value to a next tick using setTimeout
:
@Component({
selector: 'my-app',
template: `
<input id="foo" type="checkbox" [ngModel]="foo" (ngModelChange)="fooChange($event)"><label for="foo">{{foo}}</label>
`,
})
export class App {
filters:[];
foo=true
fooChange(newValue:boolean){
this.foo=newValue; // we need to make it change !
setTimeout(()=>{
if(newValue===false)
this.foo=true; // if newValue is false, foo becomes true
else
this.foo = newValue; // otherwise, do change
})
}
}
内幕发生了什么:
这篇关于Angular 2-复选框未保持同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!