Reputation: 91
I Have a unique requirement for a toggle list.
On default, all (4) toggles are true. On selecting one toggle, I want all the other toggles to set to false, while the selected one is true.
I then want to be able to select others to be true to "add on".
My code is as follows:
HTML
<mat-list class="list lt-checkbox" [ngClass]="{'selected-all': allTogglesSelected()}">
<mat-list-item>
<app-icon-switch class="toggle-all" text="All Sydney" [subText]="" icon=""
(checkedChange)="onAllChange($event)" [checked]="allTogglesSelected()">
</app-icon-switch>
</mat-list-item>
<mat-list-item>
<mat-checkbox [checked]="getFilterValue('Toggle_one')" (change)="onToggleChange('Toggle_one', $event)" color="primary"
class="toggle">Toggle 1
</mat-checkbox>
</mat-list-item>
<mat-list-item>
<mat-checkbox [checked]="getFilterValue('Toggle_two')" (change)="onToggleChange('Toggle_two', $event)"
color="primary" class="toggle">Toggle 2
</mat-checkbox>
</mat-list-item>
<mat-list-item>
<mat-checkbox [checked]="getFilterValue('Toggle_three')" (change)="onToggleChange('Toggle_three', $event)"
color="primary" class="toggle">Toggle 3
</mat-checkbox>
</mat-list-item>
<mat-list-item>
<mat-checkbox [checked]="getFilterValue('Toggle_four')" (change)="onToggleChange('Toggle_four', $event)" color="primary"
class="toggle">Toggle 4
</mat-checkbox>
</mat-list-item>
Toggle TS
private toggleRegions = ['Toggle_one', 'Toggle_two', 'Toggle_three', 'Toggle_four'];
onToggleChange(toggleState: string, value: any) {
this.toggleFilters[toggleState] = value.checked;
this.saveInStore();
}
onAllChange(value: boolean) {
const hasChanged = this.toggleRegions.some(r => this.toggleFilters[r] !== value);
if (hasChanged) {
this.toggleRegions.forEach(r => (this.toggleFilters[r] = value));
this.saveInStore();
}
}
saveInStore() {
this.store.dispatch(UpdateToggleFilter({ toggleFilters: this.toggleFilters }));
}
getFilterValue(filter: string): boolean {
return this.toggleFilters[filter];
}
allSydneySelected(): boolean {
return this.toggleRegions.findIndex(r => !this.toggleFilters[r]) === -1;
}
I've had to change some of the names for privacy reasons. Basically, it currently works as clicking on a toggle will deselect it and keep the others selected, I want the opposite.
Upvotes: 0
Views: 2585
Reputation: 569
So, It seems like you're not using Angular's powerful change detection to catch all of those value changes. this is what I would do:
in the component (please add your own types) :
firstToggle: boolean = true;
listItems = [
{
id: 'Toggle_one',
checked: true,
text: 'Toggle 1'
},
{
id: 'Toggle_two',
checked: true,
text: 'Toggle 2'
},
{
id: 'Toggle_three',
checked: true,
text: 'Toggle 3'
},
{
id: 'Toggle_four',
checked: true,
text: 'Toggle 4'
},
]
onToggleChange(id: string, value: any) {
this.listItems = this.listItems.map(item => {
if (item.id === id) {
item.checked = value.checked;
} else {
if (this.firstToggle) {
item.checked = false;
}
}
return item;
})
if (this.firstToggle) {
this.firstToggle = false;
}
this.saveInStore();
}
onAllChange(value: boolean) {
this.listItems = this.listItems.map(item => {
item.checked = value;
return item;
})
this.saveInStore();
}
saveInStore() {
this.store.dispatch(UpdateToggleFilter({ toggleFilters: this.toggleFilters }));
}
In the HTML:
<mat-list class="list lt-checkbox" [ngClass]="{'selected-all': allTogglesSelected()}">
<mat-list-item>
<app-icon-switch class="toggle-all" text="All Sydney" [subText]="" icon="" (checkedChange)="onAllChange($event)"
[checked]="allTogglesSelected()">
</app-icon-switch>
</mat-list-item>
<mat-list-item *ngFor="let item of listItems">
<mat-checkbox [checked]="item.checked" (change)="onToggleChange(item.id, $event)" color="primary"
class="toggle">{{item.text}}
</mat-checkbox>
</mat-list-item>
</mat-list>
Hopes this helps! :)
Upvotes: 1