Angular 2 - 复选框未保持同步
Posted
技术标签:
【中文标题】Angular 2 - 复选框未保持同步【英文标题】:Angular 2 - Checkbox not kept in sync 【发布时间】:2017-09-06 11:00:03 【问题描述】:我正在开发 Angular 2.0(是的,比当前的 2.4 有点落后)。
我有一个复选框列表。 我试图在 LAST CHECKBOX 未选中时做到这一点,所有 CHECKBOXES 都已选中。
<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 );
我为它创建了一个 plunker。
https://plnkr.co/edit/uzF6Lk5fxRZjXBOaS9ob?p=preview
如果未选中唯一具有 CHECKED 属性为 TRUE 的复选框,我希望所有复选框都具有 CHECKED 属性。这不会发生。
有什么想法吗?
【问题讨论】:
【参考方案1】:您应该使用ngModel
而不是绑定到checked
,并使用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);
);
plunkr
“为什么需要这样的诡计?”
实际上,因为从变化检测器的角度来看,以前的状态和新的状态之间没有变化。
所以不需要更新孩子的@Input()
/调用ControlValueAccessor
(<input type="checkbox" [ngModel]="foo">
)的writeValue()
方法。
使用 setTimeout,您首先将属性更新为 false,然后将其更改延迟回初始状态,从而允许新的更改检测周期。
另请注意,(ngModelChange)
之类的事件与更改检测周期无关。
没有setTimeout()
:
在这里,我们将得到与您的示例相同的结果,虽然我们保持 foo
为真,但复选框不会更新:
代码(plunkr):
@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()
这次我们将使用setTimeout
延迟将值重置为下一个刻度:
代码(plunkr):
@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
)
幕后发生了什么:
【讨论】:
进行了这些更改,但仍然遇到同样的问题。我添加了一个 plunker,它可能会让事情更容易理解我正在处理的情况。无论如何,感谢您的尝试。 :) 您的问题不清楚,您是否需要在最后一个未选中时允许选中/取消选中其他复选框,或者它是独占的?换句话说,取消选中最后一个复选框是检查其他复选框的快捷方式,没有任何其他约束,或者在未选中最后一个复选框时不应允许使用其他复选框? 对不起,如果我没有正确解释自己。我更新了解释。总之,我希望始终至少选中一个复选框。如果有人开始取消选中复选框,当只剩下一个复选框时,取消选中将使所有复选框都被选中。再次感谢您的宝贵时间。 曾经有另一条评论说这个超时技巧。我在等待以防其他人可以解释为什么需要这样一个可疑的技巧...... 那只是因为它没有改变!以上是关于Angular 2 - 复选框未保持同步的主要内容,如果未能解决你的问题,请参考以下文章
Angular 5,具有 3 种状态的 Angular 材质复选框(选中、未选中、不确定)
Angular 9 Reactive Forms:使用 trackBy 时复选框未更新