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 都已选中。

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 属性。这不会发生。

有什么想法吗?

【问题讨论】:

【参考方案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&lt;input type="checkbox" [ngModel]="foo"&gt;)的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 材质复选框(选中、未选中、不确定)

angular2 复选框 ng-model 未更新

Angular 9 Reactive Forms:使用 trackBy 时复选框未更新

检测在 Angular.js ng-change 事件中复选框是选中还是未选中

表单提交后选中的复选框保持选中/未选中状态

在Angular Js中重新加载后,如何将复选框(选中或未选中)从javascript控制器更新到html页面?