Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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);
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)]);
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