Skip to content

Commit

Permalink
fix(checkbox): add custom requiredTrue validator (#1105)
Browse files Browse the repository at this point in the history
* fix(checkbox): add custom required validator for template binding

* fix(checkbox): add custom required validator for template binding

* fix(checkbox): add custom required validator

* fix(checkbox): add custom required validator

* test(checkbox): remove unused tickAsync

* fix(checkbox): remove unused

* fix(checkbox): add required validator

* fix(checkbox): remove unused
  • Loading branch information
vt-allianz authored and GitHub Enterprise committed Jan 23, 2024
1 parent 38e9123 commit 081fd6a
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 12 deletions.
15 changes: 13 additions & 2 deletions projects/ng-aquila/src/checkbox/checkbox.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,15 @@ describe('NxCheckboxComponent', () => {
fixture.componentInstance.checked = false;
flushAndAssertChecked(false);
}));

it('should be invalid if required', () => {
createTestComponent(CheckboxTemplateDriven);

expect(checkboxNativeElement).toHaveClass('ng-valid');
(fixture as ComponentFixture<CheckboxTemplateDriven>).componentInstance.required = true;
fixture.detectChanges();
expect(checkboxNativeElement).toHaveClass('ng-invalid');
});
});

describe('programmatic tests', () => {
Expand Down Expand Up @@ -306,9 +315,11 @@ class CheckboxLabelSize extends CheckboxTest {}
class CheckboxOnPush extends CheckboxTest {}

@Component({
template: `<nx-checkbox [(ngModel)]="checked"></nx-checkbox>`,
template: `<nx-checkbox [(ngModel)]="checked" [required]="required"></nx-checkbox>`,
})
class CheckboxTemplateDriven extends CheckboxTest {}
class CheckboxTemplateDriven extends CheckboxTest {
required = false;
}

@Component({
template: `<nx-checkbox [negative]="negative"></nx-checkbox>`,
Expand Down
45 changes: 35 additions & 10 deletions projects/ng-aquila/src/checkbox/checkbox.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
ElementRef,
EventEmitter,
forwardRef,
Injector,
Input,
OnDestroy,
OnInit,
Expand All @@ -21,7 +22,18 @@ import {
Self,
ViewChild,
} from '@angular/core';
import { ControlValueAccessor, FormControl, FormGroupDirective, NgControl, NgForm } from '@angular/forms';
import {
AbstractControl,
ControlValueAccessor,
FormControl,
FormGroupDirective,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
NgControl,
NgForm,
ValidationErrors,
Validator,
} from '@angular/forms';
import { NxLabelComponent } from '@aposin/ng-aquila/base';
import { ErrorStateMatcher } from '@aposin/ng-aquila/utils';
import { Subject } from 'rxjs';
Expand Down Expand Up @@ -270,8 +282,20 @@ export class NxCheckboxGroupComponent implements ControlValueAccessor, AfterCont
'[attr.required]': 'required',
'[attr.aria-invalid]': '_controlInvalid() || null',
},
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NxCheckboxComponent),
multi: true,
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => NxCheckboxComponent),
multi: true,
},
],
})
export class NxCheckboxComponent implements ControlValueAccessor, OnDestroy, OnInit, AfterViewInit {
export class NxCheckboxComponent implements ControlValueAccessor, OnDestroy, OnInit, AfterViewInit, Validator {
/** @docs-private */
@ViewChild('checkboxLabelWrapper', { static: true }) _checkboxLabelWrapper!: ElementRef;

Expand Down Expand Up @@ -427,20 +451,20 @@ export class NxCheckboxComponent implements ControlValueAccessor, OnDestroy, OnI
this._cdr.detectChanges();
}

ngControl: NgControl | null = null;

constructor(
private readonly _cdr: ChangeDetectorRef,
private readonly _errorStateMatcher: ErrorStateMatcher,
@Optional() readonly checkboxGroup: NxCheckboxGroupComponent | null,
@Optional() @Self() readonly ngControl: NgControl | null,
@Optional() private readonly _parentForm: NgForm | null,
@Optional() private readonly _parentFormGroup: FormGroupDirective | null,
private readonly _focusMonitor: FocusMonitor,
) {
if (this.ngControl) {
// Note: we provide the value accessor through here, instead of
// the `providers` to avoid running into a circular import.
this.ngControl.valueAccessor = this;
}
private injector: Injector,
) {}

validate(control: AbstractControl<any, any>): ValidationErrors | null {
return this.required && control.value !== true ? { required: true } : null;
}

/** @docs-private */
Expand All @@ -453,11 +477,12 @@ export class NxCheckboxComponent implements ControlValueAccessor, OnDestroy, OnI
} else {
control = this.ngControl ? (this.ngControl.control as FormControl) : null;
}

return this._errorStateMatcher.isErrorState(control as FormControl, parent);
}

ngOnInit(): void {
this.ngControl = this.injector.get(NgControl, null);

if (this.checkboxGroup) {
this.name = this.checkboxGroup.name;
// when relevant properties of the parent like name and disabled change
Expand Down

0 comments on commit 081fd6a

Please sign in to comment.