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

Added watches for when radio buttons change and the ability to set an aria label #26

Merged
merged 2 commits into from
Mar 19, 2019
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<form [formGroup]="radioForm">
<sky-radio-group
ariaLabelledBy="radio-group-label"
class="form-group radio"
formControlName="option"
name="option"
[ariaLabel]="ariaLabel"
[ariaLabelledBy]="ariaLabelledBy"
[tabIndex]="tabIndex"
>
<legend
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ export class SkyRadioGroupTestComponent {
public radioForm: FormGroup;

public tabIndex: number;

public ariaLabelledBy: string = 'radio-group-label';

public ariaLabel: string;

public options = [
{ name: 'Lillith Corharvest', disabled: false },
{ name: 'Harima Kenji', disabled: false },
Expand All @@ -38,4 +43,13 @@ export class SkyRadioGroupTestComponent {
option: new FormControl(this.options[0])
});
}

public changeOptions(): void {
this.options = [
{ name: 'Lillith Corharvest', disabled: false },
{ name: 'Hank Salizar', disabled: false },
{ name: 'Harima Kenji', disabled: false },
{ name: 'Harry Mckenzie', disabled: false }
];
}
}
1 change: 1 addition & 0 deletions src/app/public/modules/radio/radio-group.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
class="sky-radio-group"
role="radiogroup"
[attr.aria-labelledby]="ariaLabelledBy"
[attr.aria-label]="ariaLabel"
>
<ng-content></ng-content>
</div>
82 changes: 82 additions & 0 deletions src/app/public/modules/radio/radio-group.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,46 @@ describe('Radio group component', function () {
}
}));

it('should maintain tabIndex when options change', fakeAsync(function () {
componentInstance.tabIndex = 2;
fixture.detectChanges();
tick();
fixture.detectChanges();

componentInstance.changeOptions();
fixture.detectChanges();
tick();
fixture.detectChanges();

const radios = fixture.nativeElement.querySelectorAll('input');
for (let element of radios) {
expect(element.getAttribute('tabindex')).toBe('2');
}
}));

it('should set the radio name properties correctly', fakeAsync(() => {
fixture.detectChanges();
tick();
const radios = fixture.nativeElement.querySelectorAll('input');
for (let element of radios) {
expect(element.getAttribute('name')).toBe('option');
}
}));

it('should set the radio name properties correctly when options change', fakeAsync(() => {
fixture.detectChanges();
tick();

componentInstance.changeOptions();
fixture.detectChanges();
tick();

const radios = fixture.nativeElement.querySelectorAll('input');
for (let element of radios) {
expect(element.getAttribute('name')).toBe('option');
}
}));

it('should maintain checked state when value is changed', fakeAsync(function () {
fixture.detectChanges();

Expand Down Expand Up @@ -133,6 +173,48 @@ describe('Radio group component', function () {
expect(radioDebugElement.componentInstance.checked).toBeTruthy();
}));

it('should maintain checked state when options are changed', fakeAsync(function () {
fixture.detectChanges();

let newValue = {
name: 'Jerry Salmonella',
disabled: false
};

let radioDebugElement = fixture.debugElement.query(By.css('sky-radio'));
radioDebugElement.componentInstance.value = newValue;
fixture.detectChanges();
tick();

expect(radioDebugElement.componentInstance.checked).toBeTruthy();

componentInstance.changeOptions();

fixture.detectChanges();
tick();

expect(radioDebugElement.componentInstance.checked).toBeTruthy();
}));

it('should set the aria-labeledby property correctly', fakeAsync(() => {
fixture.detectChanges();
tick();

const radioGroupDiv = fixture.nativeElement.querySelector('.sky-radio-group');
expect(radioGroupDiv.getAttribute('aria-labelledby')).toBe('radio-group-label');
}));

it('should set the aria-label property correctly', fakeAsync(() => {
componentInstance.ariaLabel = 'radio-group-label-manual';
componentInstance.ariaLabelledBy = undefined;

fixture.detectChanges();
tick();

const radioGroupDiv = fixture.nativeElement.querySelector('.sky-radio-group');
expect(radioGroupDiv.getAttribute('aria-label')).toBe('radio-group-label-manual');
}));

it('should pass accessibility', async(() => {
fixture.detectChanges();
fixture.whenStable().then(() => {
Expand Down
41 changes: 34 additions & 7 deletions src/app/public/modules/radio/radio-group.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ContentChildren,
forwardRef,
Input,
OnDestroy,
QueryList
} from '@angular/core';

Expand All @@ -13,6 +14,10 @@ import {
NG_VALUE_ACCESSOR
} from '@angular/forms';

import {
Subject
} from 'rxjs/Subject';

import {
SkyRadioChange
} from './types';
Expand All @@ -38,10 +43,13 @@ const SKY_RADIO_GROUP_CONTROL_VALUE_ACCESSOR: any = {
SKY_RADIO_GROUP_CONTROL_VALUE_ACCESSOR
]
})
export class SkyRadioGroupComponent implements AfterContentInit, ControlValueAccessor {
export class SkyRadioGroupComponent implements AfterContentInit, ControlValueAccessor, OnDestroy {
@Input()
public ariaLabelledBy: string;

@Input()
public ariaLabel: string;

@Input()
public set name(value: string) {
this._name = value;
Expand Down Expand Up @@ -82,21 +90,34 @@ export class SkyRadioGroupComponent implements AfterContentInit, ControlValueAcc
@ContentChildren(SkyRadioComponent, { descendants: true })
private radios: QueryList<SkyRadioComponent>;

private ngUnsubscribe = new Subject();

private _name = `sky-radio-group-${nextUniqueId++}`;
private _value: any;
private _tabIndex: number;

public ngAfterContentInit(): void {
this.updateCheckedRadioFromValue();
this.updateRadioButtonNames();
this.updateRadioButtonTabIndexes();
this.resetRadioButtons();

// Watch for radio selections.
this.radios.forEach((radio) => {
radio.change.subscribe((change: SkyRadioChange) => {
this.writeValue(change.value);
});
radio.change
.takeUntil(this.ngUnsubscribe)
.subscribe((change: SkyRadioChange) => {
this.writeValue(change.value);
});
});

this.radios.changes
.takeUntil(this.ngUnsubscribe)
.subscribe(() => {
this.resetRadioButtons();
});
}

public ngOnDestroy() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}

public writeValue(value: any): void {
Expand Down Expand Up @@ -145,4 +166,10 @@ export class SkyRadioGroupComponent implements AfterContentInit, ControlValueAcc
}
});
}

private resetRadioButtons(): void {
this.updateCheckedRadioFromValue();
this.updateRadioButtonNames();
this.updateRadioButtonTabIndexes();
}
}