Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion projects/igniteui-angular/combo/src/combo/combo.common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1289,6 +1289,7 @@ export abstract class IgxComboBaseDirective implements IgxComboBase, AfterViewCh
public onClick(event: Event) {
event.stopPropagation();
event.preventDefault();

if (!this.disabled) {
this.toggle();
}
Expand All @@ -1313,7 +1314,7 @@ export abstract class IgxComboBaseDirective implements IgxComboBase, AfterViewCh
}

protected onStatusChanged = () => {
if (this.ngControl && this.isTouchedOrDirty && !this.disabled) {
if (this.ngControl && this.isTouchedOrDirty && !this.ngControl.disabled) {
if (this.hasValidators && (!this.collapsed || this.inputGroup.isFocused)) {
this.valid = this.ngControl.valid ? IgxInputState.VALID : IgxInputState.INVALID;
} else {
Expand All @@ -1323,6 +1324,7 @@ export abstract class IgxComboBaseDirective implements IgxComboBase, AfterViewCh
// B.P. 18 May 2021: IgxDatePicker does not reset its state upon resetForm #9526
this.valid = IgxInputState.INITIAL;
}

this.manageRequiredAsterisk();
};

Expand Down
47 changes: 47 additions & 0 deletions projects/igniteui-angular/combo/src/combo/combo.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3345,6 +3345,7 @@ describe('igxCombo', () => {
combo = fixture.componentInstance.combo;
input = fixture.debugElement.query(By.css(`.${CSS_CLASS_INPUTGROUP}`));
});

it('should properly initialize when used as a form control', () => {
expect(combo).toBeDefined();
const comboFormReference = fixture.componentInstance.reactiveForm.controls.townCombo;
Expand Down Expand Up @@ -3375,6 +3376,7 @@ describe('igxCombo', () => {
expect(combo.valid).toEqual(IgxInputState.INITIAL);
expect(combo.comboInput.valid).toEqual(IgxInputState.INITIAL);
});

it('should properly initialize when used as a form control - without validators', () => {
const form: UntypedFormGroup = fixture.componentInstance.reactiveForm;
form.controls.townCombo.validator = null;
Expand Down Expand Up @@ -3407,6 +3409,7 @@ describe('igxCombo', () => {
expect(combo.valid).toEqual(IgxInputState.INITIAL);
expect(combo.comboInput.valid).toEqual(IgxInputState.INITIAL);
});

it('should be possible to be enabled/disabled when used as a form control', () => {
const form = fixture.componentInstance.reactiveForm;
const comboFormReference = form.controls.townCombo;
Expand Down Expand Up @@ -3439,6 +3442,47 @@ describe('igxCombo', () => {
expect(comboFormReference.disabled).toBeFalsy();
expect(combo.disabled).toBeFalsy();
});

it('should render as INITIAL after control.disable() and touched/dirty', () => {
const form = fixture.componentInstance.reactiveForm;
const control = form.controls.townCombo;

combo.select([combo.data.at(0)], true)
Comment thread
github-code-quality[bot] marked this conversation as resolved.
Fixed
fixture.detectChanges();

control.markAsTouched();
fixture.detectChanges();

expect(combo.valid).toEqual(IgxInputState.INITIAL);

control.disable();
fixture.detectChanges();

expect(combo.disabled).toBe(true);
expect(combo.valid).toEqual(IgxInputState.INITIAL);
expect(combo.comboInput.valid).toEqual(IgxInputState.INITIAL);
});

it('should render as INITIAL (not INVALID) after control.disable() and previously invalid', () => {
const form = fixture.componentInstance.reactiveForm;
const control = form.controls.townCombo;

// markAsTouched must come BEFORE setValue: markAsTouched does not emit
// statusChanges, so onStatusChanged must see touched=true at the moment
// statusChanges fires from setValue.
control.markAsTouched();
control.setValue([]);
fixture.detectChanges();

expect(combo.valid).toEqual(IgxInputState.INVALID);

control.disable();
fixture.detectChanges();

expect(combo.valid).toEqual(IgxInputState.INITIAL);
expect(combo.comboInput.valid).toEqual(IgxInputState.INITIAL);
});

it('should change value when addressed as a form control', () => {
expect(combo).toBeDefined();
const form = fixture.componentInstance.reactiveForm;
Expand All @@ -3458,6 +3502,7 @@ describe('igxCombo', () => {
fixture.detectChanges();
expect(comboFormReference.value).toEqual([{ field: 'South Carolina', region: 'South Atlantic' }]);
});

it('should properly submit values when used as a form control', () => {
expect(combo).toBeDefined();
const form = fixture.componentInstance.reactiveForm;
Expand All @@ -3473,6 +3518,7 @@ describe('igxCombo', () => {
expect(form.status).toEqual('VALID');
fixture.debugElement.query(By.css('button')).triggerEventHandler('click', UIInteractions.simulateClickAndSelectEvent);
});

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;
Expand Down Expand Up @@ -3522,6 +3568,7 @@ describe('igxCombo', () => {
expect((combo as any).inputGroup.element.nativeElement.classList.contains(CSS_CLASS_INPUT_GROUP_REQUIRED)).toBe(false);
}));
});

describe('Template form tests: ', () => {
let inputGroupRequired: DebugElement;
beforeEach(fakeAsync(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,27 @@ describe('igxSelect', () => {
expect((selectComp as any).inputGroup.element.nativeElement.classList.contains(CSS_CLASS_INPUT_GROUP_REQUIRED)).toBe(false);
}));

it('should render as INITIAL (not INVALID) after control.disable() when previously invalid', () => {
const fix = TestBed.createComponent(IgxSelectReactiveFormComponent);
fix.detectChanges();

const selectComp = fix.componentInstance.select;
const control = fix.componentInstance.reactiveForm.controls.optionsSelect;

// markAsTouched does not emit statusChanges; use updateValueAndValidity() to
// trigger onStatusChanged while touched=true so the INVALID precondition is established.
control.markAsTouched();
control.updateValueAndValidity();
fix.detectChanges();

expect(selectComp.input.valid).toEqual(IgxInputState.INVALID);

control.disable();
fix.detectChanges();

expect(selectComp.input.valid).toEqual(IgxInputState.INITIAL);
});

it('Should properly initialize when used as a form control - with initial validators', fakeAsync(() => {
const fix = TestBed.createComponent(IgxSelectTemplateFormComponent);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ export class IgxSelectComponent extends IgxDropDownComponent implements IgxSelec
if (this.disabled || this.items.length === 0) {
return;
}

if (!this.selectedItem) {
this.navigateFirst();
}
Expand Down Expand Up @@ -539,7 +540,8 @@ export class IgxSelectComponent extends IgxDropDownComponent implements IgxSelec

protected onStatusChanged() {
this.manageRequiredAsterisk();
if (this.ngControl && !this.disabled && this.isTouchedOrDirty) {

if (this.ngControl && !this.ngControl.disabled && this.isTouchedOrDirty) {
if (this.hasValidators && this.inputGroup.isFocused) {
this.input.valid = this.ngControl.valid ? IgxInputState.VALID : IgxInputState.INVALID;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2566,13 +2566,15 @@ describe('IgxSimpleCombo', () => {
]
}).compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(IgxSimpleComboInReactiveFormComponent);
fixture.detectChanges();
combo = fixture.componentInstance.reactiveCombo;
reactiveForm = fixture.componentInstance.reactiveForm;
reactiveControl = reactiveForm.form.controls['comboValue'];
});

it('should not select null, undefined and empty string in a reactive form with required', fakeAsync(() => {
// array of objects
combo.data = [
Expand Down Expand Up @@ -2685,6 +2687,7 @@ describe('IgxSimpleCombo', () => {
expect(reactiveForm.status).toEqual('INVALID');
expect(reactiveControl.status).toEqual('INVALID');
}));

it('should not select null, undefined and empty string with "writeValue" method in a reactive form with required', () => {
// array of objects
combo.data = [
Expand Down Expand Up @@ -2844,6 +2847,40 @@ describe('IgxSimpleCombo', () => {
expect(combo.value).toEqual(1);
expect(form.controls['comboValue'].value).toEqual(1);
}));

it('should render as INITIAL after control.disable() and touched/dirty', () => {
combo.select([combo.data.at(0)])
Comment thread
github-code-quality[bot] marked this conversation as resolved.
Fixed
fixture.detectChanges();

reactiveControl.markAsTouched();
fixture.detectChanges();

expect(combo.valid).toEqual(IgxInputState.INITIAL);

reactiveControl.disable();
fixture.detectChanges();

expect(combo.disabled).toBe(true);
expect(combo.valid).toEqual(IgxInputState.INITIAL);
expect(combo.comboInput.valid).toEqual(IgxInputState.INITIAL);
});

it('should render as INITIAL (not INVALID) after control.disable() and previously invalid', () => {
// markAsTouched must come BEFORE setValue: markAsTouched does not emit
// statusChanges, so onStatusChanged must see touched=true at the moment
// statusChanges fires from setValue.
reactiveControl.markAsTouched();
reactiveControl.setValue([]);
fixture.detectChanges();

expect(combo.valid).toEqual(IgxInputState.INVALID);

reactiveControl.disable();
fixture.detectChanges();

expect(combo.valid).toEqual(IgxInputState.INITIAL);
expect(combo.comboInput.valid).toEqual(IgxInputState.INITIAL);
});
});
});

Expand Down
Loading