Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(combo): update touched property and apply invalid color on blur when required - 17.2.x #14924

22 changes: 17 additions & 5 deletions projects/igniteui-angular/src/lib/combo/combo.common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1218,6 +1218,9 @@ export abstract class IgxComboBaseDirective extends DisplayDensityBase implement
/** @hidden @internal */
public handleClosed() {
this.closed.emit({ owner: this });
if(this.comboInput.nativeElement !== document.activeElement){
this.validateComboState();
}
}

/** @hidden @internal */
Expand Down Expand Up @@ -1257,14 +1260,15 @@ export abstract class IgxComboBaseDirective extends DisplayDensityBase implement
public onBlur() {
if (this.collapsed) {
this._onTouchedCallback();
if (this.ngControl && this.ngControl.invalid) {
this.valid = IgxInputState.INVALID;
} else {
this.valid = IgxInputState.INITIAL;
}
this.validateComboState();
}
}

/** @hidden @internal */
public onFocus(): void {
this._onTouchedCallback();
}

/** @hidden @internal */
public setActiveDescendant(): void {
this.activeDescendant = this.dropdown.focusedItem?.id || '';
Expand All @@ -1289,6 +1293,14 @@ export abstract class IgxComboBaseDirective extends DisplayDensityBase implement
this.manageRequiredAsterisk();
};

private validateComboState() {
if (this.ngControl && this.ngControl.invalid) {
this.valid = IgxInputState.INVALID;
} else {
this.valid = IgxInputState.INITIAL;
}
}

private get isTouchedOrDirty(): boolean {
return (this.ngControl.control.touched || this.ngControl.control.dirty);
}
Expand Down
3 changes: 2 additions & 1 deletion projects/igniteui-angular/src/lib/combo/combo.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
role="combobox" aria-haspopup="listbox"
[attr.aria-expanded]="!dropdown.collapsed" [attr.aria-controls]="dropdown.listId"
[attr.aria-labelledby]="ariaLabelledBy || label?.id || placeholder"
(blur)="onBlur()" />
(blur)="onBlur()"
(focus)="onFocus()" />
<ng-container ngProjectAs="igx-suffix">
<ng-content select="igx-suffix"></ng-content>
</ng-container>
Expand Down
23 changes: 22 additions & 1 deletion projects/igniteui-angular/src/lib/combo/combo.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3416,6 +3416,27 @@ describe('igxCombo', () => {
expect(combo.valid).toEqual(IgxInputState.INITIAL);
expect(combo.comboInput.valid).toEqual(IgxInputState.INITIAL);
}));
it('should mark as touched and invalid when combo is focused, dropdown appears, and user clicks away without selection', fakeAsync(() => {
const ngModel = fixture.debugElement.query(By.directive(NgModel)).injector.get(NgModel);
expect(combo.valid).toEqual(IgxInputState.INITIAL);
expect(combo.comboInput.valid).toEqual(IgxInputState.INITIAL);
expect(ngModel.touched).toBeFalse();

combo.open();
input.triggerEventHandler('focus', {});
fixture.detectChanges();
expect(ngModel.touched).toBeTrue();
const documentClickEvent = new MouseEvent('click', { bubbles: true });
document.body.dispatchEvent(documentClickEvent);
fixture.detectChanges();
tick();
document.body.focus();
fixture.detectChanges();
tick();
expect(combo.valid).toEqual(IgxInputState.INVALID);
expect(combo.comboInput.valid).toEqual(IgxInputState.INVALID);
expect(ngModel.touched).toBeTrue();
}));
});
});
describe('Display density', () => {
Expand Down Expand Up @@ -3627,7 +3648,7 @@ class IgxComboFormComponent {
@Component({
template: `
<form #form="ngForm">
<igx-combo #testCombo class="input-container" [placeholder]="'Locations'"
<igx-combo #testCombo #testComboNgModel="ngModel" class="input-container" [placeholder]="'Locations'"
name="anyName" required [(ngModel)]="values"
[data]="items" [filterable]="filterableFlag"
[displayKey]="'field'" [valueKey]="'field'"
Expand Down
Loading