Skip to content
This repository has been archived by the owner on Dec 8, 2022. It is now read-only.

Fix async disable selection box #280

Merged
merged 11 commits into from
Jul 16, 2021
4 changes: 1 addition & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
// Place your settings in this file to overwrite default and user settings.
{
// Columns at which to show vertical rulers
"editor.rulers": [100],
"editor.rulers": [],

// Controls after how many characters the editor will wrap to the next line. Setting this to 0 turns on viewport width wrapping (word wrapping). Setting this to -1 forces the editor to never wrap.
"editor.wordWrap": "wordWrapColumn",
"editor.wordWrapColumn": 100,

"typescript.tsdk": "node_modules/typescript/lib"
}
7 changes: 5 additions & 2 deletions src/app/public/modules/checkbox/checkbox.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
'sky-switch-control-success': checkboxType === 'success',
'sky-switch-control-warning': checkboxType === 'warning',
'sky-switch-control-danger': checkboxType === 'danger'
}">
}"
>
<sky-icon *ngIf="icon || checked"
class="sky-checkbox-icon-default"
fixedWidth="true"
Expand All @@ -42,7 +43,9 @@
[icon]="icon"
>
</sky-icon>
<ng-template #checkedTemplate>
<ng-template
#checkedTemplate
>
<sky-icon *ngIf="checked"
class="sky-checkbox-icon-modern-checked"
fixedWidth="true"
Expand Down
32 changes: 27 additions & 5 deletions src/app/public/modules/checkbox/checkbox.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
DebugElement
DebugElement,
ViewChild
} from '@angular/core';

import {
ComponentFixture,
async,
ComponentFixture,
fakeAsync,
TestBed
} from '@angular/core/testing';

Expand All @@ -32,7 +35,7 @@ import {

import {
SkyCheckboxChange
} from '../checkbox/checkbox-change';
} from './checkbox-change';

import {
SkyCheckboxComponent
Expand Down Expand Up @@ -60,15 +63,27 @@ import {
</sky-checkbox>
</div>`
})
class SingleCheckboxComponent {
class SingleCheckboxComponent implements AfterViewInit {
public checkboxType: string;
public icon: string = 'bold';
public isChecked: boolean = false;
public isDisabled: boolean = false;

@ViewChild(SkyCheckboxComponent)
public checkboxComponent: SkyCheckboxComponent;

public ngAfterViewInit() {
this.checkboxComponent.disabledChange.subscribe((value) => {
this.onDisabledChange(value);
});
}

public onDisabledChange(value: boolean): void {}

public checkboxChange($event: any) {
this.isChecked = $event.checked;
}

}

/** Simple component for testing an MdCheckbox with ngModel. */
Expand Down Expand Up @@ -309,6 +324,14 @@ describe('Checkbox component', () => {
});
}));

it('should emit the new disabled value when it is modified', fakeAsync(() => {
const onDisabledChangeSpy = spyOn(testComponent, 'onDisabledChange');
expect(onDisabledChangeSpy).toHaveBeenCalledTimes(0);
testComponent.isDisabled = true;
fixture.detectChanges();
expect(onDisabledChangeSpy).toHaveBeenCalledTimes(1);
}));

it('should add and remove the checked state', () => {
expect(checkboxInstance.checked).toBe(false);
expect(inputElement.checked).toBe(false);
Expand Down Expand Up @@ -400,7 +423,6 @@ describe('Checkbox component', () => {
expect(fixture.nativeElement).toBeAccessible();
});
}));

});

describe('with change event and no initial value', () => {
Expand Down
39 changes: 34 additions & 5 deletions src/app/public/modules/checkbox/checkbox.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,23 @@ export class SkyCheckboxComponent implements ControlValueAccessor, OnInit {

/**
* Indicates whether to disable the checkbox.
* @default false
*/
@Input()
public disabled: boolean = false;
@Input()
public set disabled(value: boolean) {
const coercedValue = SkyFormsUtility.coerceBooleanProperty(value);
if (coercedValue !== this.disabled) {
this._disabled = coercedValue;
this._disabledChange.next(this._disabled);
}
}

/**
* Indicates whether the checkbox is disabled.
*/
public get disabled() {
return this._disabled;
}

/**
* Specifies an index for the checkbox. If not defined, the index is set to the position of the
Expand Down Expand Up @@ -145,9 +159,12 @@ export class SkyCheckboxComponent implements ControlValueAccessor, OnInit {
}
}

public get checked() {
return this._checked;
}
/**
* Indicates whether the checkbox is selected.
*/
public get checked() {
return this._checked;
}

/**
* Indicates whether the input is required for form validation.
Expand All @@ -173,6 +190,14 @@ export class SkyCheckboxComponent implements ControlValueAccessor, OnInit {
return this._checkedChange;
}

/**
* Fires when the selected value changes.
*/
@Output()
public get disabledChange(): Observable<boolean> {
return this._disabledChange;
}

private isFirstChange = true;

private _checkboxType: string;
Expand All @@ -181,6 +206,10 @@ export class SkyCheckboxComponent implements ControlValueAccessor, OnInit {

private _checkedChange = new BehaviorSubject<boolean>(this._checked);

private _disabled: boolean = false;

private _disabledChange = new BehaviorSubject<boolean>(this._disabled);

private _required: boolean = false;

constructor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
<div
role="radiogroup"
aria-labelledby="radio-group-label">

<sky-radio
id="hey-2"
id="hey"
name="testName"
[disabled]="disabled1"
[label]="label1"
[value]="value1"
[(ngModel)]="selectedValue"
Expand All @@ -22,9 +24,8 @@
</sky-radio>

<sky-radio
id="hey"
id="hey-2"
name="testName"
[disabled]="disabled2"
[tabindex]="tabindex2"
[value]="value2"
[(ngModel)]="selectedValue"
Expand All @@ -33,6 +34,7 @@
My label
</sky-radio-label>
</sky-radio>

<sky-radio
id="hey-3"
name="testName"
Expand All @@ -44,6 +46,7 @@
My label
</sky-radio-label>
</sky-radio>

</div>

<sky-radio
Expand Down
23 changes: 20 additions & 3 deletions src/app/public/modules/radio/fixtures/radio.component.fixture.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import {
Component
AfterViewInit,
Component,
ViewChild
} from '@angular/core';

import {
SkyRadioComponent
} from '../radio.component';

@Component({
templateUrl: './radio.component.fixture.html'
})
export class SkyRadioTestComponent {
export class SkyRadioTestComponent implements AfterViewInit {
public selectedValue = '1';
public disabled2 = false;
public disabled1 = false;

public value1 = '1';
public value2 = '2';
Expand All @@ -18,5 +24,16 @@ export class SkyRadioTestComponent {

public tabindex2: string;

@ViewChild(SkyRadioComponent)
public checkboxComponent: SkyRadioComponent;

public ngAfterViewInit() {
this.checkboxComponent.disabledChange.subscribe((value) => {
this.onDisabledChange(value);
});
}

public onDisabledChange(value: boolean): void {}

public onClick() {}
}
6 changes: 4 additions & 2 deletions src/app/public/modules/radio/radio.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
'sky-switch-control-success': icon && radioType === 'success',
'sky-switch-control-warning': icon && radioType === 'warning',
'sky-switch-control-danger': icon && radioType === 'danger'
}">
}"
>
<sky-icon *ngIf="icon || checked"
class="sky-radio-icon-default"
fixedWidth="true"
Expand All @@ -44,7 +45,8 @@
<ng-template #checkedTemplate>
<div *ngIf="checked"
class="sky-radio-icon-modern-checked sky-rounded-circle"
></div>
>
</div>
</ng-template>
</div>
</span>
Expand Down
42 changes: 29 additions & 13 deletions src/app/public/modules/radio/radio.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,26 @@ describe('Radio component', function () {
});

describe('Standard radio component', () => {
beforeEach(fakeAsync(function () {
let testComponent: SkyRadioTestComponent;

beforeEach(fakeAsync(() => {
fixture = TestBed.createComponent(SkyRadioTestComponent);

componentInstance = fixture.componentInstance;
testComponent = fixture.debugElement.componentInstance;

fixture.detectChanges();
tick();
componentInstance = fixture.componentInstance;
}));

it('should emit the new disabled value when it is modified', () => {
const onDisabledChangeSpy = spyOn(testComponent, 'onDisabledChange');
expect(onDisabledChangeSpy).toHaveBeenCalledTimes(0);
testComponent.disabled1 = true;
fixture.detectChanges();
expect(onDisabledChangeSpy).toHaveBeenCalledTimes(1);
});

it('should update the ngModel properly when radio button is changed', fakeAsync(function () {
let radioElement = fixture.debugElement.queryAll(By.directive(SkyRadioComponent))[0];
let ngModel = <NgModel>radioElement.injector.get(NgModel);
Expand Down Expand Up @@ -147,32 +159,36 @@ describe('Radio component', function () {
}));

it('should handle disabled state properly', fakeAsync(function () {
componentInstance.disabled2 = true;
fixture.detectChanges();
tick();

const radios = fixture.nativeElement.querySelectorAll('input');
radios.item(1).click();
fixture.detectChanges();
tick();

expect(radios.item(0).checked).toBeTruthy();
expect(radios.item(1).checked).toBeFalsy();
expect(radios.item(2).checked).toBeFalsy();
expect(componentInstance.selectedValue).toBe('1');

componentInstance.disabled2 = false;
componentInstance.disabled1 = true;
fixture.detectChanges();
tick();

radios.item(1).click();
radios.item(0).click();
fixture.detectChanges();
tick();

expect(radios.item(0).checked).toBeFalsy();
expect(radios.item(1).checked).toBeTruthy();
expect(radios.item(2).checked).toBeFalsy();
expect(componentInstance.selectedValue).toBe('2');

componentInstance.disabled1 = false;
fixture.detectChanges();
tick();

radios.item(0).click();
fixture.detectChanges();
tick();

expect(radios.item(0).checked).toBeTruthy();
expect(radios.item(1).checked).toBeFalsy();
expect(radios.item(2).checked).toBeFalsy();
expect(componentInstance.selectedValue).toBe('1');
}));

it('should pass a label when specified', fakeAsync(function () {
Expand Down
16 changes: 13 additions & 3 deletions src/app/public/modules/radio/radio.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,10 @@ export class SkyRadioComponent implements OnDestroy, ControlValueAccessor {
*/
@Input()
public set disabled(value: boolean) {
const newDisabledState = SkyFormsUtility.coerceBooleanProperty(value);
bradenbiz marked this conversation as resolved.
Show resolved Hide resolved
if (this._disabled !== newDisabledState) {
this._disabled = newDisabledState;
const coercedValue = SkyFormsUtility.coerceBooleanProperty(value);
if (coercedValue !== this.disabled) {
this._disabled = coercedValue;
this._disabledChange.next(this._disabled);
this.changeDetector.markForCheck();
}
}
Expand Down Expand Up @@ -238,6 +239,14 @@ export class SkyRadioComponent implements OnDestroy, ControlValueAccessor {
return this._checkedChange;
}

/**
* Fires when the selected value changes.
*/
@Output()
public get disabledChange(): Observable<boolean> {
return this._disabledChange;
}

public get inputId(): string {
return `sky-radio-${this.id}-input`;
}
Expand All @@ -255,6 +264,7 @@ export class SkyRadioComponent implements OnDestroy, ControlValueAccessor {
private _checked = false;
private _checkedChange = new BehaviorSubject<boolean>(this._checked);
private _disabled: boolean = false;
private _disabledChange = new BehaviorSubject<boolean>(this._disabled);
private _name: string;
private _radioType: string;
private _selectedValue: any;
Expand Down
Loading