From f6768608ad36fced030848555d551f9aa6bece56 Mon Sep 17 00:00:00 2001 From: Stamen Stoychev Date: Mon, 14 Jul 2025 17:03:35 +0300 Subject: [PATCH 1/7] fix(combo): bypassing require logic applied by igxInput --- projects/igniteui-angular/src/lib/combo/combo.component.html | 1 + 1 file changed, 1 insertion(+) diff --git a/projects/igniteui-angular/src/lib/combo/combo.component.html b/projects/igniteui-angular/src/lib/combo/combo.component.html index 9e795a6f3d3..52422c4a939 100644 --- a/projects/igniteui-angular/src/lib/combo/combo.component.html +++ b/projects/igniteui-angular/src/lib/combo/combo.component.html @@ -9,6 +9,7 @@ Date: Thu, 26 Jun 2025 10:21:04 +0300 Subject: [PATCH 2/7] fix(combo): Sync aria required with required state --- projects/igniteui-angular/src/lib/combo/combo.common.ts | 1 + .../igniteui-angular/src/lib/combo/combo.component.spec.ts | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/projects/igniteui-angular/src/lib/combo/combo.common.ts b/projects/igniteui-angular/src/lib/combo/combo.common.ts index e24df49dbc5..469215f3d7d 100644 --- a/projects/igniteui-angular/src/lib/combo/combo.common.ts +++ b/projects/igniteui-angular/src/lib/combo/combo.common.ts @@ -1343,6 +1343,7 @@ export abstract class IgxComboBaseDirective implements IgxComboBase, AfterViewCh protected manageRequiredAsterisk(): void { if (this.ngControl) { this.inputGroup.isRequired = this.required; + this.comboInput.nativeElement.setAttribute('aria-required', this.required.toString()); } } diff --git a/projects/igniteui-angular/src/lib/combo/combo.component.spec.ts b/projects/igniteui-angular/src/lib/combo/combo.component.spec.ts index 6f35b59aa24..75ac3d3c9a9 100644 --- a/projects/igniteui-angular/src/lib/combo/combo.component.spec.ts +++ b/projects/igniteui-angular/src/lib/combo/combo.component.spec.ts @@ -3436,8 +3436,11 @@ describe('igxCombo', () => { it('should add/remove asterisk when setting validators dynamically', () => { let inputGroupIsRequiredClass = fixture.debugElement.query(By.css('.' + CSS_CLASS_INPUTGROUP_REQUIRED)); let asterisk = window.getComputedStyle(fixture.debugElement.query(By.css('.' + CSS_CLASS_INPUTGROUP_LABEL)).nativeElement, ':after').content; + input = fixture.debugElement.query(By.css(`.${CSS_CLASS_COMBO_INPUTGROUP}`)); expect(asterisk).toBe('"*"'); expect(inputGroupIsRequiredClass).toBeDefined(); + console.log(input.nativeElement); + expect(input.nativeElement.getAttribute('aria-required')).toMatch('true'); fixture.componentInstance.reactiveForm.controls.townCombo.clearValidators(); fixture.componentInstance.reactiveForm.controls.townCombo.updateValueAndValidity(); @@ -3446,6 +3449,7 @@ describe('igxCombo', () => { asterisk = window.getComputedStyle(fixture.debugElement.query(By.css('.' + CSS_CLASS_INPUTGROUP_LABEL)).nativeElement, ':after').content; expect(asterisk).toBe('none'); expect(inputGroupIsRequiredClass).toBeNull(); + expect(input.nativeElement.getAttribute('aria-required')).toMatch('false'); fixture.componentInstance.reactiveForm.controls.townCombo.setValidators(Validators.required); fixture.componentInstance.reactiveForm.controls.townCombo.updateValueAndValidity(); @@ -3454,6 +3458,7 @@ describe('igxCombo', () => { asterisk = window.getComputedStyle(fixture.debugElement.query(By.css('.' + CSS_CLASS_INPUTGROUP_LABEL)).nativeElement, ':after').content; expect(asterisk).toBe('"*"'); expect(inputGroupIsRequiredClass).toBeDefined(); + expect(input.nativeElement.getAttribute('aria-required')).toMatch('true'); }); it('Should update validity state when programmatically setting errors on reactive form controls', fakeAsync(() => { From e649e4f6d7f9eb1bd22edf2c724a1ec68ae207fc Mon Sep 17 00:00:00 2001 From: Stamen Stoychev Date: Thu, 24 Jul 2025 14:49:31 +0300 Subject: [PATCH 3/7] feat(*): adding external validator logic for input --- .../src/lib/combo/combo.common.ts | 4 ++++ .../src/lib/combo/combo.component.html | 2 +- .../lib/directives/input/input.directive.ts | 19 ++++++++++++++++++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/projects/igniteui-angular/src/lib/combo/combo.common.ts b/projects/igniteui-angular/src/lib/combo/combo.common.ts index 469215f3d7d..7772fadd37c 100644 --- a/projects/igniteui-angular/src/lib/combo/combo.common.ts +++ b/projects/igniteui-angular/src/lib/combo/combo.common.ts @@ -1300,6 +1300,10 @@ export abstract class IgxComboBaseDirective implements IgxComboBase, AfterViewCh this.manageRequiredAsterisk(); }; + protected externalValidate(): IgxInputState { + return this._valid; + } + private updateValidity() { if (this.ngControl && this.ngControl.invalid) { this.valid = IgxInputState.INVALID; diff --git a/projects/igniteui-angular/src/lib/combo/combo.component.html b/projects/igniteui-angular/src/lib/combo/combo.component.html index 52422c4a939..7c470190ccd 100644 --- a/projects/igniteui-angular/src/lib/combo/combo.component.html +++ b/projects/igniteui-angular/src/lib/combo/combo.component.html @@ -9,7 +9,7 @@ IgxInputState = null; constructor( public inputGroup: IgxInputGroupBase, @@ -195,6 +196,20 @@ export class IgxInputDirective implements AfterViewInit, OnDestroy { this.nativeElement.required = this.inputGroup.isRequired = value; } + /** + * @hidden @internal + * Sets a function to validate the input externally. + * This function should return an `IgxInputState` value. + */ + @Input() + public set externalValidate(fn: () => IgxInputState) { + this._externalValidate = fn; + } + + public get externalValidate(): () => IgxInputState { + return this._externalValidate; + } + /** * Gets whether the igxInput is required. * @@ -367,7 +382,9 @@ export class IgxInputDirective implements AfterViewInit, OnDestroy { * @internal */ protected updateValidityState() { - if (this.ngControl) { + if (this._externalValidate) { + this._valid = this._externalValidate(); + } else if (this.ngControl) { if (!this.disabled && this.isTouchedOrDirty) { if (this.hasValidators) { // Run the validation with empty object to check if required is enabled. From 8394a01a8549f3d8641693a27634422e221e086f Mon Sep 17 00:00:00 2001 From: Stamen Stoychev Date: Thu, 24 Jul 2025 15:23:26 +0300 Subject: [PATCH 4/7] fix(*): adding required props for input --- projects/igniteui-angular/src/lib/combo/combo.component.html | 1 + 1 file changed, 1 insertion(+) diff --git a/projects/igniteui-angular/src/lib/combo/combo.component.html b/projects/igniteui-angular/src/lib/combo/combo.component.html index 7c470190ccd..b97ae325338 100644 --- a/projects/igniteui-angular/src/lib/combo/combo.component.html +++ b/projects/igniteui-angular/src/lib/combo/combo.component.html @@ -9,6 +9,7 @@ Date: Fri, 25 Jul 2025 17:59:09 +0300 Subject: [PATCH 5/7] feat(*): aria-required date-picker and simple combo --- projects/igniteui-angular/src/lib/combo/combo.common.ts | 1 + .../src/lib/date-picker/date-picker.component.html | 1 + .../src/lib/date-picker/date-picker.component.spec.ts | 4 ++++ .../src/lib/simple-combo/simple-combo.component.html | 1 + .../src/lib/simple-combo/simple-combo.component.spec.ts | 1 + 5 files changed, 8 insertions(+) diff --git a/projects/igniteui-angular/src/lib/combo/combo.common.ts b/projects/igniteui-angular/src/lib/combo/combo.common.ts index 7772fadd37c..294cda4f38b 100644 --- a/projects/igniteui-angular/src/lib/combo/combo.common.ts +++ b/projects/igniteui-angular/src/lib/combo/combo.common.ts @@ -1300,6 +1300,7 @@ export abstract class IgxComboBaseDirective implements IgxComboBase, AfterViewCh this.manageRequiredAsterisk(); }; + /** @hidden @internal */ protected externalValidate(): IgxInputState { return this._valid; } diff --git a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.html b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.html index 81159a032bd..29a0c74fbbe 100644 --- a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.html +++ b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.html @@ -15,6 +15,7 @@ } { expect(datePicker).toBeDefined(); expect(inputGroup.isRequired).toBeTruthy(); + expect((datePicker as any).inputDirective.nativeElement.getAttribute('aria-required')).toEqual('true'); }); it('should update inputGroup isRequired correctly', () => { const inputGroup = (datePicker as any).inputGroup; + const inputEl = (datePicker as any).inputDirective.nativeElement; expect(datePicker).toBeDefined(); expect(inputGroup.isRequired).toBeTruthy(); + expect(inputEl.getAttribute('aria-required')).toEqual('true'); (fixture.componentInstance as IgxDatePickerNgModelComponent).isRequired = false; fixture.detectChanges(); expect(inputGroup.isRequired).toBeFalsy(); + expect(inputEl.getAttribute('aria-required')).toEqual('false'); }); it('should set validity to initial when the form is reset', fakeAsync(() => { diff --git a/projects/igniteui-angular/src/lib/simple-combo/simple-combo.component.html b/projects/igniteui-angular/src/lib/simple-combo/simple-combo.component.html index 21252f137c7..af6d8cbdc57 100644 --- a/projects/igniteui-angular/src/lib/simple-combo/simple-combo.component.html +++ b/projects/igniteui-angular/src/lib/simple-combo/simple-combo.component.html @@ -13,6 +13,7 @@ { expect(combo.valid).toEqual(IgxInputState.INITIAL); expect(combo.comboInput.valid).toEqual(IgxInputState.INITIAL); + expect(combo.comboInput.nativeElement.attributes['aria-required']).toBeDefined(); // empty string combo.open(); From 97e25ffcea9c4360fdf51c35058efa08e9ce6504 Mon Sep 17 00:00:00 2001 From: Stamen Stoychev Date: Fri, 25 Jul 2025 18:13:14 +0300 Subject: [PATCH 6/7] fix(tests): making the check working --- .../src/lib/date-picker/date-picker.component.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.spec.ts b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.spec.ts index e486a7509ab..a91acf26ad5 100644 --- a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.spec.ts +++ b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.spec.ts @@ -246,7 +246,7 @@ describe('IgxDatePicker', () => { fixture.detectChanges(); expect(inputGroup.isRequired).toBeFalsy(); - expect(inputEl.getAttribute('aria-required')).toEqual('false'); + expect(inputEl.getAttribute('aria-required')).toEqual(null); }); it('should set validity to initial when the form is reset', fakeAsync(() => { From ef71a877c56de3dbc2f3f23485e23680ae2ee2d2 Mon Sep 17 00:00:00 2001 From: Stamen Stoychev Date: Fri, 25 Jul 2025 18:42:08 +0300 Subject: [PATCH 7/7] chore(combo): modifying existing commit --- projects/igniteui-angular/src/lib/combo/combo.common.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/projects/igniteui-angular/src/lib/combo/combo.common.ts b/projects/igniteui-angular/src/lib/combo/combo.common.ts index 294cda4f38b..24d19f77b39 100644 --- a/projects/igniteui-angular/src/lib/combo/combo.common.ts +++ b/projects/igniteui-angular/src/lib/combo/combo.common.ts @@ -1348,7 +1348,6 @@ export abstract class IgxComboBaseDirective implements IgxComboBase, AfterViewCh protected manageRequiredAsterisk(): void { if (this.ngControl) { this.inputGroup.isRequired = this.required; - this.comboInput.nativeElement.setAttribute('aria-required', this.required.toString()); } }