diff --git a/projects/components/src/toggle-switch/toggle-switch.component.test.ts b/projects/components/src/toggle-switch/toggle-switch.component.test.ts index 563ccabfa..1547e4ade 100644 --- a/projects/components/src/toggle-switch/toggle-switch.component.test.ts +++ b/projects/components/src/toggle-switch/toggle-switch.component.test.ts @@ -1,6 +1,6 @@ import { CommonModule } from '@angular/common'; import { fakeAsync } from '@angular/core/testing'; -import { FormsModule } from '@angular/forms'; +import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { MatSlideToggle, MatSlideToggleChange, MatSlideToggleModule } from '@angular/material/slide-toggle'; import { createHostFactory, Spectator } from '@ngneat/spectator/jest'; import { ToggleSwitchSize } from './toggle-switch-size'; @@ -12,7 +12,7 @@ describe('Toggle Switch Component', () => { const createHost = createHostFactory({ component: ToggleSwitchComponent, shallow: true, - imports: [MatSlideToggleModule, FormsModule, CommonModule] + imports: [MatSlideToggleModule, FormsModule, CommonModule, ReactiveFormsModule] }); test('should pass properties to Mat Slide toggle correctly', fakeAsync(() => { @@ -41,4 +41,20 @@ describe('Toggle Switch Component', () => { spectator.triggerEventHandler(MatSlideToggle, 'change', new MatSlideToggleChange(matToggleComponent!, false)); expect(onCheckedChangeSpy).toHaveBeenCalledWith(false); })); + + test('should work correctly with control value accessor', () => { + const formControl = new FormControl(false); + spectator = createHost(``, { + hostProps: { + formControl: formControl + } + }); + expect(spectator.component.isChecked).toBe(false); + + formControl.setValue(true); + expect(spectator.component.isChecked).toBe(true); + + formControl.disable(); + expect(spectator.component.isDisabled).toBe(true); + }); }); diff --git a/projects/components/src/toggle-switch/toggle-switch.component.ts b/projects/components/src/toggle-switch/toggle-switch.component.ts index aa897013d..9a3598bbf 100644 --- a/projects/components/src/toggle-switch/toggle-switch.component.ts +++ b/projects/components/src/toggle-switch/toggle-switch.component.ts @@ -1,4 +1,5 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core'; +import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; import { MatSlideToggleChange } from '@angular/material/slide-toggle'; import { ToggleSwitchSize } from './toggle-switch-size'; @@ -10,33 +11,81 @@ import { ToggleSwitchSize } from './toggle-switch-size';
{{ this.label }}
- ` + `, + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: ToggleSwitchComponent, + multi: true + } + ] }) -export class ToggleSwitchComponent { +export class ToggleSwitchComponent implements ControlValueAccessor { @Input() - public checked?: boolean; + public label?: string = ''; @Input() - public label?: string = ''; + public size: ToggleSwitchSize = ToggleSwitchSize.Small; @Input() - public disabled?: boolean; + public set checked(checked: boolean | undefined) { + this.isChecked = checked ?? false; + } + + public get checked(): boolean { + return this.isChecked; + } @Input() - public size: ToggleSwitchSize = ToggleSwitchSize.Small; + public set disabled(disabled: boolean | undefined) { + this.isDisabled = disabled ?? false; + } + + public get disabled(): boolean { + return this.isDisabled; + } @Output() public readonly checkedChange: EventEmitter = new EventEmitter(); + public isChecked: boolean = false; + public isDisabled: boolean = false; + + private onTouched!: () => void; + private onChanged!: (value: boolean) => void; + + public constructor(private readonly cdr: ChangeDetectorRef) {} + public onToggle(toggleChange: MatSlideToggleChange): void { - this.checkedChange.emit(toggleChange.checked); + this.isChecked = toggleChange.checked; + this.checkedChange.emit(this.isChecked); + this.onChanged(this.isChecked); + this.onTouched(); + } + + public registerOnChange(fn: (value: boolean) => void): void { + this.onChanged = fn; + } + + public registerOnTouched(fn: () => void): void { + this.onTouched = fn; + } + + public setDisabledState(isDisabled: boolean): void { + this.isDisabled = isDisabled; + this.cdr.markForCheck(); + } + + public writeValue(isChecked: boolean | undefined): void { + this.isChecked = isChecked ?? false; + this.cdr.markForCheck(); } }