Skip to content

Commit

Permalink
fix(igx-input): add support for disabled attr without value
Browse files Browse the repository at this point in the history
  • Loading branch information
jackofdiamond5 committed Mar 9, 2021
1 parent 49c4e88 commit 3885913
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Component, ViewChild, ViewChildren, QueryList, DebugElement } from '@angular/core';
import { TestBed, fakeAsync, tick, waitForAsync } from '@angular/core/testing';
import { FormsModule, FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { FormsModule, FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { By } from '@angular/platform-browser';
import { IgxInputGroupComponent, IgxInputGroupModule } from '../../input-group/input-group.component';
import { IgxInputDirective, IgxInputState } from './input.directive';
Expand Down Expand Up @@ -32,6 +32,7 @@ describe('IgxInput', () => {
RequiredInputComponent,
RequiredTwoWayDataBoundInputComponent,
DataBoundDisabledInputComponent,
DataBoundDisabledInputWithoutValueComponent,
ReactiveFormComponent,
InputsWithSameNameAttributesComponent,
ToggleRequiredWithNgModelInputComponent
Expand All @@ -42,7 +43,7 @@ describe('IgxInput', () => {
ReactiveFormsModule
]
})
.compileComponents();
.compileComponents();
}));

it('Initializes an input.', () => {
Expand Down Expand Up @@ -186,6 +187,25 @@ describe('IgxInput', () => {
expect(igxInput.disabled).toBe(true);
});

it('should have disabled style if disabled attr is set without value', () => {
const fixture = TestBed.createComponent(DataBoundDisabledInputWithoutValueComponent);
fixture.detectChanges();

const igxInput = fixture.componentInstance.igxInput;
const inputElement = fixture.debugElement.query(By.directive(IgxInputDirective)).nativeElement;
const inputGroupElement = fixture.debugElement.query(By.css('igx-input-group')).nativeElement;
expect(inputGroupElement.classList.contains(INPUT_GROUP_DISABLED_CSS_CLASS)).toBe(true);
expect(inputElement.disabled).toBe(true);
expect(igxInput.disabled).toBe(true);

fixture.componentInstance.changeDisabledState();
fixture.detectChanges();

expect(inputGroupElement.classList.contains(INPUT_GROUP_DISABLED_CSS_CLASS)).toBe(false);
expect(inputElement.disabled).toBe(false);
expect(igxInput.disabled).toBe(false);
});

it('should style required input correctly.', () => {
const fixture = TestBed.createComponent(RequiredInputComponent);
fixture.detectChanges();
Expand Down Expand Up @@ -645,7 +665,8 @@ describe('IgxInput', () => {
});
});

@Component({ template: `
@Component({
template: `
<form>
<igx-input-group #igxInputGroup>
<label for="firstName" #igxLabel igxLabel>Name</label>
Expand All @@ -666,7 +687,8 @@ class InputsWithSameNameAttributesComponent {
}


@Component({ template: `<igx-input-group #igxInputGroup>
@Component({
template: `<igx-input-group #igxInputGroup>
<label for="test" igxLabel>Test</label>
<input name="test" #igxInput type="text" igxInput />
</igx-input-group>` })
Expand All @@ -675,22 +697,25 @@ class InputComponent {
@ViewChild(IgxInputDirective, { static: true }) public igxInput: IgxInputDirective;
}

@Component({ template: `<igx-input-group>
@Component({
template: `<igx-input-group>
<label for="test" igxLabel>Test</label>
<textarea name="test" igxInput></textarea>
</igx-input-group>` })
class TextareaComponent {
}

@Component({ template: `<igx-input-group>
@Component({
template: `<igx-input-group>
<label for="test" igxLabel>Test</label>
<input name="test" placeholder="Test" #igxInput type="text" igxInput />
</igx-input-group>` })
class InputWithPlaceholderComponent {
@ViewChild(IgxInputDirective, { static: true }) public igxInput: IgxInputDirective;
}

@Component({ template: `<igx-input-group #igxInputGroup>
@Component({
template: `<igx-input-group #igxInputGroup>
<label for="test" igxLabel>Test</label>
<input name="test" #igxInput type="text" igxInput value="Test" />
</igx-input-group>` })
Expand All @@ -699,7 +724,8 @@ class FilledInputComponent {
@ViewChild(IgxInputDirective, { static: true }) public igxInput: IgxInputDirective;
}

@Component({ template: `<igx-input-group #igxInputGroup>
@Component({
template: `<igx-input-group #igxInputGroup>
<label for="test" igxLabel>Test</label>
<input name="test" #igxInput type="text" igxInput value="Test" disabled="disabled" />
</igx-input-group>` })
Expand All @@ -708,7 +734,8 @@ class DisabledInputComponent {
@ViewChild(IgxInputDirective, { static: true }) public igxInput: IgxInputDirective;
}

@Component({ template: `<igx-input-group #igxInputGroup>
@Component({
template: `<igx-input-group #igxInputGroup>
<label for="test" igxLabel>Test</label>
<input name="test" #igxInput type="text" igxInput required="required" />
</igx-input-group>` })
Expand All @@ -717,7 +744,8 @@ class RequiredInputComponent {
@ViewChild(IgxInputDirective, { static: true }) public igxInput: IgxInputDirective;
}

@Component({ template: `<igx-input-group #igxInputGroup>
@Component({
template: `<igx-input-group #igxInputGroup>
<label for="test" igxLabel>Test</label>
<input name="test" #igxInput type="text" igxInput [(ngModel)]="user.firstName" required="required" />
</igx-input-group>` })
Expand All @@ -730,7 +758,8 @@ class RequiredTwoWayDataBoundInputComponent {
};
}

@Component({ template: `<igx-input-group #igxInputGroupNotFilledUndefined>
@Component({
template: `<igx-input-group #igxInputGroupNotFilledUndefined>
<label for="not-filled-undefined" igxLabel>Not Filled Undefined</label>
<input name="not-filled-undefined" igxInput [(ngModel)]="notFilledUndefined" />
</igx-input-group>
Expand Down Expand Up @@ -793,7 +822,8 @@ class InitiallyFilledInputComponent {
};
}

@Component({ template: `<igx-input-group #igxInputGroup>
@Component({
template: `<igx-input-group #igxInputGroup>
<label for="test" igxLabel>Test</label>
<input name="test" #igxInput type="text" igxInput [disabled]="disabled" />
</igx-input-group>` })
Expand All @@ -804,9 +834,21 @@ class DataBoundDisabledInputComponent {
public disabled = false;
}

@Component({
template: `<igx-input-group #igxInputGroup>
<label for="test" igxLabel>Test</label>
<input name="test" #igxInput type="text" igxInput disabled />
</igx-input-group>`
})
class DataBoundDisabledInputWithoutValueComponent extends DataBoundDisabledInputComponent {
public changeDisabledState() {
this.igxInput.disabled = !this.igxInput.disabled;
}
}

@Component({
template:
`<form class="wrapper" [formGroup]="form">
`<form class="wrapper" [formGroup]="form">
<section>
<igx-input-group>
<label igxLabel>single line</label>
Expand Down Expand Up @@ -855,7 +897,8 @@ class ReactiveFormComponent {
}
}

@Component({ template: `<igx-input-group>
@Component({
template: `<igx-input-group>
<label for="test" igxLabel>Test</label>
<input name="test" type="text" igxInput [(ngModel)]="data" [required]="isRequired"/>
</igx-input-group>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
Input,
OnDestroy,
Optional,
Self,
Self
} from '@angular/core';
import {
AbstractControl,
Expand Down Expand Up @@ -98,6 +98,7 @@ export class IgxInputDirective implements AfterViewInit, OnDestroy {
private _valid = IgxInputState.INITIAL;
private _statusChanges$: Subscription;
private _fileNames: string;
private _disabled = false;

constructor(
public inputGroup: IgxInputGroupBase,
Expand All @@ -108,7 +109,7 @@ export class IgxInputDirective implements AfterViewInit, OnDestroy {
protected formControl: FormControlName,
protected element: ElementRef<HTMLInputElement>,
protected cdr: ChangeDetectorRef
) {}
) { }

private get ngControl(): NgControl {
return this.ngModel ? this.ngModel : this.formControl;
Expand Down Expand Up @@ -153,8 +154,10 @@ export class IgxInputDirective implements AfterViewInit, OnDestroy {
*/
@Input()
public set disabled(value: boolean) {
this.nativeElement.disabled = value;
this.inputGroup.disabled = value;
// handle case when disabled attr is set with no value
this._disabled = value != null && `${value}` !== 'false';
this.nativeElement.disabled = this._disabled;
this.inputGroup.disabled = this._disabled;
}
/**
* Gets the `disabled` property
Expand All @@ -167,7 +170,10 @@ export class IgxInputDirective implements AfterViewInit, OnDestroy {
* ```
*/
public get disabled() {
return this.nativeElement.hasAttribute('disabled');
if (this.ngControl && this.ngControl.disabled !== null) {
return this.ngControl.disabled;
}
return this._disabled = this.nativeElement.disabled;
}

/**
Expand Down Expand Up @@ -342,8 +348,8 @@ export class IgxInputDirective implements AfterViewInit, OnDestroy {
if (!this.disabled && (this.ngControl.control.touched || this.ngControl.control.dirty)) {
// the control is not disabled and is touched or dirty
this._valid = this.ngControl.invalid ?
IgxInputState.INVALID : this.focused ? IgxInputState.VALID :
IgxInputState.INITIAL;
IgxInputState.INVALID : this.focused ? IgxInputState.VALID :
IgxInputState.INITIAL;
} else {
// if control is untouched, pristine, or disabled its state is initial. This is when user did not interact
// with the input or when form/control is reset
Expand Down Expand Up @@ -449,8 +455,8 @@ export class IgxInputDirective implements AfterViewInit, OnDestroy {
private checkNativeValidity() {
if (!this.disabled && this._hasValidators()) {
this._valid = this.nativeElement.checkValidity() ?
this.focused ? IgxInputState.VALID : IgxInputState.INITIAL :
IgxInputState.INVALID;
this.focused ? IgxInputState.VALID : IgxInputState.INITIAL :
IgxInputState.INVALID;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ describe('IgxInputGroup', () => {
InputGroupDisabledComponent,
InputGroupDisabledByDefaultComponent,
InputGroupCosyDisplayDensityComponent,
InputGroupDisabledWithoutValueComponent,
InputGroupCompactDisplayDensityComponent,
InputGroupInputDisplayDensityComponent
],
imports: [
IgxInputGroupModule, IgxIconModule
]
})
.compileComponents();
.compileComponents();
}));

it('Initializes an input group.', () => {
Expand Down Expand Up @@ -147,6 +148,24 @@ describe('IgxInputGroup', () => {
expect(igxInputGroup.disabled).toBeTruthy();
});

it('should handle disabled attribute without value', () => {
pending();
const fixture = TestBed.createComponent(InputGroupDisabledWithoutValueComponent);
fixture.detectChanges();

const component = fixture.componentInstance;
const igxInputGroup = component.igxInputGroup;
expect(igxInputGroup.disabled).toBeTruthy();

component.changeDisableState();
fixture.detectChanges();
expect(igxInputGroup.disabled).toBeFalsy();

component.changeDisableState();
fixture.detectChanges();
expect(igxInputGroup.disabled).toBeTruthy();
});

it('default Display Density applied', () => {
const fixture = TestBed.createComponent(InputGroupDisabledByDefaultComponent);
fixture.detectChanges();
Expand Down Expand Up @@ -348,6 +367,20 @@ class InputGroupDisabledComponent {
}
}

@Component({
template: `<igx-input-group #igxInputGroup disabled>
<input igxInput />
</igx-input-group>`
})
class InputGroupDisabledWithoutValueComponent {
@ViewChild('igxInputGroup')
public igxInputGroup: IgxInputGroupComponent;

public changeDisableState() {
this.igxInputGroup.disabled = !this.igxInputGroup.disabled;
}
}

@Component({
template: `<igx-input-group #igxInputGroup [disabled]="disabled">
<input igxInput />
Expand Down

0 comments on commit 3885913

Please sign in to comment.