Angular 2 - 复选框未保持同步

时间:2017-04-11 07:31:36

标签: angular checkbox angular2-forms

我正在研究Angular 2.0(是的,有点落后于当前的2.4)。

我有一个复选框列表。 我试图在未检查到最后的复选框时检查所有的复选框。

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

}

我为它创造了一个plunker。

https://plnkr.co/edit/uzF6Lk5fxRZjXBOaS9ob?p=preview

如果取消选中CHECKED属性为TRUE的唯一复选框,我希望所有复选框都具有CHECKED属性。这不会发生。

enter image description here

有什么想法吗?

1 个答案:

答案 0 :(得分:11)

您应该使用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

&#34;为什么需要这种鱼腥技巧?&#34;

实际上,因为从变更检测器的角度来看,之前的状态与新状态之间没有变化。

因此,无需更新孩子的@Input() /调用ControlValueAccessor writeValue()的{​​{1}}方法。

使用setTimeout,首先将属性更新为false,然后将其更改延迟回初始状态,从而允许新的更改检测周期。

另请注意,<input type="checkbox" [ngModel]="foo">等事件与更改检测周期无关。

没有(ngModelChange)

在这里,我们会得到与您的示例相同的结果,当我们保持setTimeout()为真时,复选框不会更新:

代码(plunkr):

foo

幕后发生了什么:

enter image description here

使用@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()

延迟将值重置为下一个刻度

代码(plunkr):

setTimeout

幕后发生了什么:

enter image description here