Skip to content

Commit b5d2785

Browse files
committed
feat(toggle): add control value accessor
1 parent 3520581 commit b5d2785

File tree

2 files changed

+63
-10
lines changed

2 files changed

+63
-10
lines changed

projects/components/src/toggle-switch/toggle-switch.component.test.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { CommonModule } from '@angular/common';
22
import { fakeAsync } from '@angular/core/testing';
3-
import { FormsModule } from '@angular/forms';
3+
import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
44
import { MatSlideToggle, MatSlideToggleChange, MatSlideToggleModule } from '@angular/material/slide-toggle';
55
import { createHostFactory, Spectator } from '@ngneat/spectator/jest';
66
import { ToggleSwitchSize } from './toggle-switch-size';
@@ -12,7 +12,7 @@ describe('Toggle Switch Component', () => {
1212
const createHost = createHostFactory({
1313
component: ToggleSwitchComponent,
1414
shallow: true,
15-
imports: [MatSlideToggleModule, FormsModule, CommonModule]
15+
imports: [MatSlideToggleModule, FormsModule, CommonModule, ReactiveFormsModule]
1616
});
1717

1818
test('should pass properties to Mat Slide toggle correctly', fakeAsync(() => {
@@ -41,4 +41,20 @@ describe('Toggle Switch Component', () => {
4141
spectator.triggerEventHandler(MatSlideToggle, 'change', new MatSlideToggleChange(matToggleComponent!, false));
4242
expect(onCheckedChangeSpy).toHaveBeenCalledWith(false);
4343
}));
44+
45+
test('should work correctly with control value accessor', () => {
46+
const formControl = new FormControl(false);
47+
spectator = createHost(`<ht-toggle-switch [label]="label" [formControl]="formControl"></ht-toggle-switch>`, {
48+
hostProps: {
49+
formControl: formControl
50+
}
51+
});
52+
expect(spectator.component.isChecked).toBe(false);
53+
54+
formControl.setValue(true);
55+
expect(spectator.component.isChecked).toBe(true);
56+
57+
formControl.disable();
58+
expect(spectator.component.isDisabled).toBe(true);
59+
});
4460
});
Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
2+
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
23
import { MatSlideToggleChange } from '@angular/material/slide-toggle';
34
import { ToggleSwitchSize } from './toggle-switch-size';
45

@@ -10,33 +11,69 @@ import { ToggleSwitchSize } from './toggle-switch-size';
1011
<div class="toggle-switch">
1112
<mat-slide-toggle
1213
color="primary"
13-
[checked]="this.checked"
14+
[checked]="this.isChecked"
1415
[ngClass]="{ 'small-slide-toggle': this.size === '${ToggleSwitchSize.Small}', disabled: this.disabled }"
15-
[disabled]="this.disabled"
16+
[disabled]="this.isDisabled"
1617
(change)="this.onToggle($event)"
1718
>
1819
<div class="label">{{ this.label }}</div>
1920
</mat-slide-toggle>
2021
</div>
21-
`
22+
`,
23+
providers: [
24+
{
25+
provide: NG_VALUE_ACCESSOR,
26+
useExisting: ToggleSwitchComponent,
27+
multi: true
28+
}
29+
]
2230
})
23-
export class ToggleSwitchComponent {
31+
export class ToggleSwitchComponent implements ControlValueAccessor {
2432
@Input()
25-
public checked?: boolean;
33+
public label?: string = '';
2634

2735
@Input()
28-
public label?: string = '';
36+
public set checked(checked: boolean | undefined) {
37+
this.isChecked = checked ?? false;
38+
}
2939

3040
@Input()
31-
public disabled?: boolean;
41+
public set disabled(disabled: boolean | undefined) {
42+
this.isDisabled = disabled ?? false;
43+
}
3244

3345
@Input()
3446
public size: ToggleSwitchSize = ToggleSwitchSize.Small;
3547

3648
@Output()
3749
public readonly checkedChange: EventEmitter<boolean> = new EventEmitter();
3850

51+
public isChecked: boolean = false;
52+
public isDisabled: boolean = false;
53+
54+
private onTouched!: () => void;
55+
private onChanged!: (value: boolean) => void;
56+
3957
public onToggle(toggleChange: MatSlideToggleChange): void {
40-
this.checkedChange.emit(toggleChange.checked);
58+
this.isChecked = toggleChange.checked;
59+
this.checkedChange.emit(this.isChecked);
60+
this.onChanged(this.isChecked);
61+
this.onTouched();
62+
}
63+
64+
public registerOnChange(fn: (value: boolean) => void): void {
65+
this.onChanged = fn;
66+
}
67+
68+
public registerOnTouched(fn: () => void): void {
69+
this.onTouched = fn;
70+
}
71+
72+
public setDisabledState(isDisabled: boolean): void {
73+
this.isDisabled = isDisabled;
74+
}
75+
76+
public writeValue(isChecked: boolean | undefined): void {
77+
this.isChecked = isChecked ?? false;
4178
}
4279
}

0 commit comments

Comments
 (0)