Skip to content

Commit 1f75158

Browse files
fix(radio-group): keyboard navigation issues in dialog (#12815)
* fix(radio-group): keyboard navigation issues in dialog * fix(radio-group): prevent focusing two buttons at a time * style(radio-group): update style --------- Co-authored-by: Simeon Simeonoff <[email protected]>
1 parent 3270e41 commit 1f75158

File tree

1 file changed

+57
-4
lines changed

1 file changed

+57
-4
lines changed

projects/igniteui-angular/src/lib/directives/radio/radio-group.directive.ts

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {
22
AfterContentInit,
33
AfterViewInit,
4-
ContentChildren, Directive, EventEmitter, HostBinding, HostListener, Input, NgModule, OnDestroy, Optional, Output, QueryList, Self
4+
ContentChildren, Directive, DoCheck, EventEmitter, HostBinding, HostListener, Input, NgModule, OnDestroy, Optional, Output, QueryList, Self
55
} from '@angular/core';
66
import { ControlValueAccessor, NgControl, Validators } from '@angular/forms';
77
import { fromEvent, noop, Subject } from 'rxjs';
@@ -49,7 +49,7 @@ let nextId = 0;
4949
exportAs: 'igxRadioGroup',
5050
selector: 'igx-radio-group, [igxRadioGroup]'
5151
})
52-
export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit, ControlValueAccessor, OnDestroy {
52+
export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit, ControlValueAccessor, OnDestroy, DoCheck {
5353
private static ngAcceptInputType_required: boolean | '';
5454
private static ngAcceptInputType_invalid: boolean | '';
5555
/**
@@ -204,10 +204,10 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
204204
@HostListener('keydown', ['$event'])
205205
protected handleKeyDown(event: KeyboardEvent) {
206206
const { key } = event;
207+
const buttons = this.radioButtons.filter(radio => !radio.disabled);
208+
const checked = buttons.find((radio) => radio.checked);
207209

208210
if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(key)) {
209-
const buttons = this.radioButtons.filter(radio => !radio.disabled);
210-
const checked = buttons.find((radio) => radio.checked);
211211
let index = checked ? buttons.indexOf(checked!) : -1;
212212
const ltr = this._directionality.value === 'ltr';
213213

@@ -238,6 +238,14 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
238238
buttons[index].select();
239239
event.preventDefault();
240240
}
241+
242+
if (event.key === "Tab") {
243+
buttons.forEach((radio) => {
244+
if (radio !== checked) {
245+
event.stopPropagation();
246+
}
247+
});
248+
}
241249
}
242250

243251
/**
@@ -352,6 +360,12 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
352360
.subscribe(() => {
353361
this.updateValidityOnBlur()
354362
});
363+
364+
fromEvent(button.nativeElement, 'keyup')
365+
.pipe(takeUntil(this.destroy$))
366+
.subscribe((event: KeyboardEvent) => {
367+
this.updateOnKeyUp(event)
368+
});
355369
});
356370
}
357371
}
@@ -371,6 +385,45 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
371385
}
372386
}
373387

388+
/**
389+
* @hidden
390+
* @internal
391+
*/
392+
private updateOnKeyUp(event: KeyboardEvent) {
393+
const checked = this.radioButtons.find(x => x.checked);
394+
395+
if (event.key === "Tab") {
396+
this.radioButtons.forEach((radio) => {
397+
if (radio === checked) {
398+
checked.focused = true;
399+
}
400+
});
401+
}
402+
}
403+
404+
public ngDoCheck(): void {
405+
this._updateTabIndex();
406+
}
407+
408+
private _updateTabIndex() {
409+
// Needed so that the keyboard navigation of a radio group
410+
// placed inside a dialog works properly
411+
if (this.radioButtons) {
412+
const checked = this.radioButtons.find(x => x.checked);
413+
414+
if (checked) {
415+
this.radioButtons.forEach((button) => {
416+
checked.nativeElement.tabIndex = 0;
417+
418+
if (button !== checked) {
419+
button.nativeElement.tabIndex = -1;
420+
button.focused = false;
421+
}
422+
});
423+
}
424+
}
425+
}
426+
374427
/**
375428
* Sets the "checked" property value on the radio input element.
376429
*

0 commit comments

Comments
 (0)