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
If unchecked the only checkbox with CHECKED attribute TRUE, Im expecting that ALL checkboxes would have CHECKED attribute. This does not happen.
Any ideas?
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);
});
}
}
plunkr
Actually, because from change-detector's point of view, there is no change between the previous state and the new one.
So there is no need to update the @Input()
of the child /call the writeValue()
method of the ControlValueAccessor
(<input type="checkbox" [ngModel]="foo">
).
Using setTimeout, you first update the property to false, then delay its change back to initial state, allowing a new change-detection cycle.
Also note that events like (ngModelChange)
are not correlated to the change-detection cycle.
setTimeout()
: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
})
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With