Angular 2 - 复选框不同步

标签 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

有什么想法吗?

最佳答案

你应该使用 ngModel而不是绑定(bind)到 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

“为什么需要这样的诡计?”

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

因此无需更新 @Input() child 的/调用writeValue() ControlValueAccessor 的方法(<input type="checkbox" [ngModel]="foo">)。

使用 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
  }
}

引擎盖下发生了什么:

enter image description here

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

引擎盖下发生了什么:

enter image description here

关于Angular 2 - 复选框不同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43339450/

相关文章:

node.js - 如何为生产准备 nodejs?

javascript - 单击复选框清除表单字段

javascript - 将数据绑定(bind)到 Angular 复选框

angular2-forms - Angular Form Builder 可选 必填字段

Angular2 指令 - 具有多个 ID 的选择器

angular - 在多个位置输出/渲染模板,与 ngIf 条件分开

javascript - Angular 2 : Array. 推送无法正常工作

angular - Dart Angular 组件OptionGroup:LabelFunction

java - Android 更改 CheckBox 选中的颜色

Angular2 patchValue 将值插入数组