|
1 | 1 | import {
|
2 | 2 | AfterContentInit,
|
3 | 3 | AfterViewInit,
|
4 |
| - ContentChildren, Directive, EventEmitter, HostBinding, Input, NgModule, OnDestroy, Optional, Output, QueryList, Self |
| 4 | + ContentChildren, Directive, EventEmitter, HostBinding, HostListener, Input, NgModule, OnDestroy, Optional, Output, QueryList, Self |
5 | 5 | } from '@angular/core';
|
6 | 6 | import { ControlValueAccessor, NgControl, Validators } from '@angular/forms';
|
7 | 7 | import { fromEvent, noop, Subject } from 'rxjs';
|
8 | 8 | import { startWith, takeUntil } from 'rxjs/operators';
|
9 | 9 | import { mkenum } from '../../core/utils';
|
10 | 10 | import { IChangeRadioEventArgs, IgxRadioComponent } from '../../radio/radio.component';
|
| 11 | +import { IgxDirectionality } from '../../services/direction/directionality'; |
11 | 12 | import { IgxRippleModule } from '../ripple/ripple.directive';
|
12 | 13 |
|
13 | 14 | /**
|
@@ -194,6 +195,51 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
|
194 | 195 | @HostBinding('class.igx-radio-group--vertical')
|
195 | 196 | private vertical = false;
|
196 | 197 |
|
| 198 | + @HostListener('click', ['$event']) |
| 199 | + protected handleClick(event: MouseEvent) { |
| 200 | + event.stopPropagation(); |
| 201 | + this.selected.nativeElement.focus(); |
| 202 | + } |
| 203 | + |
| 204 | + @HostListener('keydown', ['$event']) |
| 205 | + protected handleKeyDown(event: KeyboardEvent) { |
| 206 | + const { key } = event; |
| 207 | + |
| 208 | + if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(key)) { |
| 209 | + const buttons = this.radioButtons.filter(radio => !radio.disabled); |
| 210 | + const checked = buttons.find((radio) => radio.checked); |
| 211 | + let index = checked ? buttons.indexOf(checked!) : -1; |
| 212 | + const ltr = this._directionality.value === 'ltr'; |
| 213 | + |
| 214 | + switch (key) { |
| 215 | + case 'ArrowUp': |
| 216 | + index += -1; |
| 217 | + break; |
| 218 | + case 'ArrowLeft': |
| 219 | + index += ltr ? -1 : 1; |
| 220 | + break; |
| 221 | + case 'ArrowRight': |
| 222 | + index += ltr ? 1 : -1; |
| 223 | + break; |
| 224 | + default: |
| 225 | + index += 1; |
| 226 | + } |
| 227 | + |
| 228 | + if (index < 0) index = buttons.length - 1; |
| 229 | + if (index > buttons.length - 1) index = 0; |
| 230 | + |
| 231 | + buttons.forEach((radio) => { |
| 232 | + radio.deselect(); |
| 233 | + radio.nativeElement.blur(); |
| 234 | + }); |
| 235 | + |
| 236 | + buttons[index].focused = true; |
| 237 | + buttons[index].nativeElement.focus(); |
| 238 | + buttons[index].select(); |
| 239 | + event.preventDefault(); |
| 240 | + } |
| 241 | + } |
| 242 | + |
197 | 243 | /**
|
198 | 244 | * Returns the alignment of the `igx-radio-group`.
|
199 | 245 | * ```typescript
|
@@ -284,8 +330,8 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
|
284 | 330 | });
|
285 | 331 | }
|
286 | 332 |
|
287 |
| - /** |
288 |
| - * @hidden |
| 333 | + /** |
| 334 | + * @hidden |
289 | 335 | * @internal
|
290 | 336 | */
|
291 | 337 | public ngAfterViewInit() {
|
@@ -315,6 +361,10 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
|
315 | 361 | * @internal
|
316 | 362 | */
|
317 | 363 | private updateValidityOnBlur() {
|
| 364 | + this.radioButtons.forEach((button) => { |
| 365 | + button.focused = false; |
| 366 | + }); |
| 367 | + |
318 | 368 | if (this.required) {
|
319 | 369 | const checked = this.radioButtons.find(x => x.checked);
|
320 | 370 | this.invalid = !checked;
|
@@ -372,7 +422,8 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
|
372 | 422 |
|
373 | 423 | constructor(
|
374 | 424 | @Optional() @Self() public ngControl: NgControl,
|
375 |
| - ) { |
| 425 | + private _directionality: IgxDirectionality, |
| 426 | + ) { |
376 | 427 | if (this.ngControl !== null) {
|
377 | 428 | this.ngControl.valueAccessor = this;
|
378 | 429 | }
|
|
0 commit comments