11import {
2- AfterContentInit ,
3- AfterViewInit ,
42 ChangeDetectorRef ,
5- ContentChildren , Directive , DoCheck , EventEmitter , HostBinding , HostListener , Input , OnDestroy , Optional , Output , QueryList , Self , booleanAttribute ,
6- contentChildren
3+ Directive , DoCheck , EventEmitter , HostBinding , HostListener , Input , OnDestroy , Optional , Output , Self , booleanAttribute ,
4+ contentChildren ,
5+ effect ,
6+ signal
77} from '@angular/core' ;
88import { ControlValueAccessor , NgControl , Validators } from '@angular/forms' ;
9- import { fromEvent , noop , Subject } from 'rxjs' ;
10- import { startWith , takeUntil } from 'rxjs/operators' ;
9+ import { fromEvent , noop , Subject , takeUntil } from 'rxjs' ;
1110import { mkenum } from '../../core/utils' ;
1211import { IgxRadioComponent } from '../../radio/radio.component' ;
1312import { IgxDirectionality } from '../../services/direction/directionality' ;
@@ -52,7 +51,7 @@ let nextId = 0;
5251 selector : 'igx-radio-group, [igxRadioGroup]' ,
5352 standalone : true
5453} )
55- export class IgxRadioGroupDirective implements AfterContentInit , AfterViewInit , ControlValueAccessor , OnDestroy , DoCheck {
54+ export class IgxRadioGroupDirective implements ControlValueAccessor , OnDestroy , DoCheck {
5655 /**
5756 * Returns reference to the child radio buttons.
5857 *
@@ -61,9 +60,7 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
6160 * let radioButtons = this.radioGroup.radioButtons;
6261 * ```
6362 */
64- @ContentChildren ( IgxRadioComponent , { descendants : true } ) public radioButtons : QueryList < IgxRadioComponent > ;
65-
66- public RadioBtnSignal = contentChildren ( IgxRadioComponent , { descendants : true } ) ;
63+ public radioButtons = contentChildren ( IgxRadioComponent , { descendants : true } ) ;
6764
6865 /**
6966 * Sets/gets the `value` attribute.
@@ -207,7 +204,7 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
207204 */
208205 @HostBinding ( 'class.igx-radio-group--before' )
209206 protected get labelBefore ( ) {
210- return this . RadioBtnSignal ( ) . some ( ( radio ) => radio . labelPosition === 'before' ) ;
207+ return this . radioButtons ( ) . some ( ( radio ) => radio . labelPosition === 'before' ) ;
211208 }
212209
213210 /**
@@ -219,7 +216,7 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
219216 */
220217 @HostBinding ( 'class.igx-radio-group--disabled' )
221218 protected get disabled ( ) {
222- return this . RadioBtnSignal ( ) . every ( ( radio ) => radio . disabled ) ;
219+ return this . radioButtons ( ) . every ( ( radio ) => radio . disabled ) ;
223220 }
224221
225222 @HostListener ( 'click' , [ '$event' ] )
@@ -234,7 +231,7 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
234231 @HostListener ( 'keydown' , [ '$event' ] )
235232 protected handleKeyDown ( event : KeyboardEvent ) {
236233 const { key } = event ;
237- const buttons = this . radioButtons . filter ( radio => ! radio . disabled ) ;
234+ const buttons = this . radioButtons ( ) . filter ( radio => ! radio . disabled ) ;
238235 const checked = buttons . find ( ( radio ) => radio . checked ) ;
239236
240237 if ( [ 'ArrowUp' , 'ArrowDown' , 'ArrowLeft' , 'ArrowRight' ] . includes ( key ) ) {
@@ -331,7 +328,7 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
331328 * @hidden
332329 * @internal
333330 */
334- private _isInitialized = false ;
331+ private _isInitialized = signal ( false ) ;
335332 /**
336333 * @hidden
337334 * @internal
@@ -353,68 +350,13 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
353350 */
354351 private queryChange$ = new Subject < void > ( ) ;
355352
356- /**
357- * @hidden
358- * @internal
359- */
360- public ngAfterContentInit ( ) {
361- // The initial value can possibly be set by NgModel and it is possible that
362- // the OnInit of the NgModel occurs after the OnInit of this class.
363- this . _isInitialized = true ;
364-
365- this . radioButtons . changes . pipe ( startWith ( 0 ) , takeUntil ( this . destroy$ ) ) . subscribe ( ( ) => {
366- this . queryChange$ . next ( ) ;
367- setTimeout ( ( ) => this . _initRadioButtons ( ) ) ;
368- } ) ;
369-
370-
371- if ( this . ngControl ) {
372- this . radioButtons . forEach ( ( button ) => {
373- if ( this . ngControl . disabled ) {
374- button . disabled = this . ngControl . disabled ;
375- }
376- } ) ;
377- }
378- }
379-
380- /**
381- * @hidden
382- * @internal
383- */
384- public ngAfterViewInit ( ) {
385- if ( this . ngControl ) {
386- this . ngControl . statusChanges . pipe ( takeUntil ( this . destroy$ ) ) . subscribe ( ( ) => {
387- this . invalid = false ;
388- } ) ;
389-
390- if ( this . ngControl . control . validator || this . ngControl . control . asyncValidator ) {
391- this . _required = this . ngControl ?. control ?. hasValidator ( Validators . required ) ;
392- }
393- }
394-
395- if ( this . radioButtons ) {
396- this . radioButtons . forEach ( ( button ) => {
397- button . blurRadio
398- . pipe ( takeUntil ( this . destroy$ ) )
399- . subscribe ( ( ) => {
400- this . updateValidityOnBlur ( )
401- } ) ;
402-
403- fromEvent ( button . nativeElement , 'keyup' )
404- . pipe ( takeUntil ( this . destroy$ ) )
405- . subscribe ( ( event : KeyboardEvent ) => {
406- this . updateOnKeyUp ( event )
407- } ) ;
408- } ) ;
409- }
410- }
411353
412354 /**
413355 * @hidden
414356 * @internal
415357 */
416358 private updateValidityOnBlur ( ) {
417- this . radioButtons . forEach ( ( button ) => {
359+ this . radioButtons ( ) . forEach ( ( button ) => {
418360 button . focused = false ;
419361
420362 if ( button . invalid ) {
@@ -428,10 +370,10 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
428370 * @internal
429371 */
430372 private updateOnKeyUp ( event : KeyboardEvent ) {
431- const checked = this . radioButtons . find ( x => x . checked ) ;
373+ const checked = this . radioButtons ( ) . find ( x => x . checked ) ;
432374
433375 if ( event . key === "Tab" ) {
434- this . radioButtons . forEach ( ( radio ) => {
376+ this . radioButtons ( ) . forEach ( ( radio ) => {
435377 if ( radio === checked ) {
436378 checked . focused = true ;
437379 }
@@ -447,10 +389,10 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
447389 // Needed so that the keyboard navigation of a radio group
448390 // placed inside a dialog works properly
449391 if ( this . radioButtons ) {
450- const checked = this . radioButtons . find ( x => x . checked ) ;
392+ const checked = this . radioButtons ( ) . find ( x => x . checked ) ;
451393
452394 if ( checked ) {
453- this . radioButtons . forEach ( ( button ) => {
395+ this . radioButtons ( ) . forEach ( ( button ) => {
454396 checked . nativeElement . tabIndex = 0 ;
455397
456398 if ( button !== checked ) {
@@ -496,7 +438,7 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
496438 */
497439 public registerOnTouched ( fn : ( ) => void ) {
498440 if ( this . radioButtons ) {
499- this . radioButtons . forEach ( ( button ) => {
441+ this . radioButtons ( ) . forEach ( ( button ) => {
500442 button . registerOnTouched ( fn ) ;
501443 } ) ;
502444 }
@@ -519,39 +461,86 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
519461 if ( this . ngControl !== null ) {
520462 this . ngControl . valueAccessor = this ;
521463 }
464+
465+ effect ( ( ) => {
466+ this . initialize ( ) ;
467+ this . setRadioButtons ( ) ;
468+ } )
522469 }
523470
524471 /**
525472 * @hidden
526473 * @internal
527474 */
528- private _initRadioButtons ( ) {
529- if ( this . radioButtons ) {
530- const props = { name : this . _name , required : this . _required } ;
531- this . radioButtons . forEach ( ( button ) => {
532- Object . assign ( button , props ) ;
533-
534- if ( button . value === this . _value ) {
535- button . checked = true ;
536- this . _selected = button ;
537- this . cdr . markForCheck ( ) ;
538- }
475+ private initialize ( ) {
476+ // The initial value can possibly be set by NgModel and it is possible that
477+ // the OnInit of the NgModel occurs after the OnInit of this class.
478+ this . _isInitialized . set ( true ) ;
479+
480+ if ( this . ngControl ) {
481+ this . ngControl . statusChanges
482+ . pipe ( takeUntil ( this . destroy$ ) )
483+ . subscribe ( ( ) => {
484+ this . invalid = false ;
485+ } ) ;
486+
487+ if ( this . ngControl . control . validator || this . ngControl . control . asyncValidator ) {
488+ this . _required = this . ngControl ?. control ?. hasValidator ( Validators . required ) ;
489+ }
539490
540- button . change . pipe (
541- takeUntil ( button . destroy$ ) ,
542- takeUntil ( this . destroy$ ) ,
543- takeUntil ( this . queryChange$ )
544- ) . subscribe ( ( ev ) => this . _selectedRadioButtonChanged ( ev ) ) ;
491+ this . radioButtons ( ) . forEach ( ( button ) => {
492+ if ( this . ngControl . disabled ) {
493+ button . disabled = this . ngControl . disabled ;
494+ }
545495 } ) ;
546496 }
547497 }
548498
499+ /**
500+ * @hidden
501+ * @internal
502+ */
503+ private setRadioButtons ( ) {
504+ this . radioButtons ( ) . forEach ( ( button ) => {
505+ button . name = this . _name ;
506+ button . required = this . _required ;
507+
508+ if ( button . value === this . _value ) {
509+ button . checked = true ;
510+ this . _selected = button ;
511+ this . cdr . markForCheck ( ) ;
512+ }
513+
514+ this . _setRadioButtonEvents ( button ) ;
515+ } ) ;
516+ }
517+
518+ /**
519+ * @hidden
520+ * @internal
521+ */
522+ private _setRadioButtonEvents ( button : any ) {
523+ button . change . pipe (
524+ takeUntil ( button . destroy$ ) ,
525+ takeUntil ( this . destroy$ ) ,
526+ takeUntil ( this . queryChange$ )
527+ ) . subscribe ( ( ev ) => this . _selectedRadioButtonChanged ( ev ) ) ;
528+
529+ button . blurRadio
530+ . pipe ( takeUntil ( this . destroy$ ) )
531+ . subscribe ( ( ) => this . updateValidityOnBlur ( ) ) ;
532+
533+ fromEvent ( button . nativeElement , 'keyup' )
534+ . pipe ( takeUntil ( this . destroy$ ) )
535+ . subscribe ( ( event : KeyboardEvent ) => this . updateOnKeyUp ( event ) ) ;
536+ }
537+
549538 /**
550539 * @hidden
551540 * @internal
552541 */
553542 private _selectedRadioButtonChanged ( args : IChangeCheckboxEventArgs ) {
554- this . radioButtons . forEach ( ( button ) => {
543+ this . radioButtons ( ) . forEach ( ( button ) => {
555544 button . checked = button . id === args . owner . id ;
556545 if ( button . checked && button . ngControl ) {
557546 this . invalid = button . ngControl . invalid ;
@@ -575,7 +564,7 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
575564 */
576565 private _setRadioButtonNames ( ) {
577566 if ( this . radioButtons ) {
578- this . radioButtons . forEach ( ( button ) => {
567+ this . radioButtons ( ) . forEach ( ( button ) => {
579568 button . name = this . _name ;
580569 } ) ;
581570 }
@@ -587,7 +576,7 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
587576 */
588577 private _selectRadioButton ( ) {
589578 if ( this . radioButtons ) {
590- this . radioButtons . forEach ( ( button ) => {
579+ this . radioButtons ( ) . forEach ( ( button ) => {
591580 if ( this . _value === null ) {
592581 // no value - uncheck all radio buttons
593582 if ( button . checked ) {
@@ -620,7 +609,7 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
620609 */
621610 private _setRadioButtonsRequired ( ) {
622611 if ( this . radioButtons ) {
623- this . radioButtons . forEach ( ( button ) => {
612+ this . radioButtons ( ) . forEach ( ( button ) => {
624613 button . required = this . _required ;
625614 } ) ;
626615 }
@@ -632,7 +621,7 @@ export class IgxRadioGroupDirective implements AfterContentInit, AfterViewInit,
632621 */
633622 private _setRadioButtonsInvalid ( ) {
634623 if ( this . radioButtons ) {
635- this . radioButtons . forEach ( ( button ) => {
624+ this . radioButtons ( ) . forEach ( ( button ) => {
636625 button . invalid = this . _invalid ;
637626 } ) ;
638627 }
0 commit comments