@@ -11,7 +11,8 @@ import {
1111 Output ,
1212 QueryList ,
1313 Renderer2 ,
14- HostBinding
14+ HostBinding ,
15+ AfterViewInit
1516} from "@angular/core" ;
1617import { NG_VALUE_ACCESSOR , ControlValueAccessor } from "@angular/forms" ;
1718import { Radio } from "./radio.component" ;
@@ -24,16 +25,17 @@ import { Radio } from "./radio.component";
2425export class RadioChange {
2526 /**
2627 * Contains the `Radio` that has been changed.
27- * @type {(Radio | null) }
28- * @memberof RadioChange
2928 */
3029 source : Radio | null ;
3130 /**
3231 * The value of the `Radio` encompassed in the `RadioChange` class.
33- * @type {any }
34- * @memberof RadioChange
3532 */
36- value : any ;
33+ value : string ;
34+
35+ constructor ( source : Radio , value : string ) {
36+ this . source = source ;
37+ this . value = value ;
38+ }
3739}
3840
3941/**
@@ -77,15 +79,14 @@ export class RadioChange {
7779 }
7880 ]
7981} )
80- export class RadioGroup implements OnInit , AfterContentInit , ControlValueAccessor {
82+ export class RadioGroup implements AfterContentInit , AfterViewInit , ControlValueAccessor {
8183 /**
8284 * Used for creating the `RadioGroup` 'name' property dynamically.
8385 */
8486 static radioGroupCount = 0 ;
8587
8688 /**
8789 * Emits event notifying other classes of a change using a `RadioChange` class.
88- * @type {EventEmitter<RadioChange> }
8990 */
9091 @Output ( ) change : EventEmitter < RadioChange > = new EventEmitter < RadioChange > ( ) ;
9192
@@ -95,38 +96,27 @@ export class RadioGroup implements OnInit, AfterContentInit, ControlValueAccesso
9596 // tslint:disable-next-line:no-forward-ref
9697 @ContentChildren ( forwardRef ( ( ) => Radio ) ) radios : QueryList < Radio > ;
9798
98- /**
99- * Determines the render size of the `Radio` inputs within the group.
100- */
101- @Input ( ) size : "sm" | "md" = "md" ;
102-
103- /**
104- * Returns the `Radio` that is selected within the `RadioGroup`.
105- * @readonly
106- */
107- @Input ( )
108- get selected ( ) {
109- return this . _selected ;
110- }
11199 /**
112100 * Sets the passed in `Radio` item as the selected input within the `RadioGroup`.
113101 */
102+ @Input ( )
114103 set selected ( selected : Radio | null ) {
115104 this . _selected = selected ;
116105 this . value = selected ? selected . value : null ;
117106 this . checkSelectedRadio ( ) ;
118107 }
119108
120109 /**
121- * Returns the value/state of the selected `Radio` within the `RadioGroup`.
110+ * Returns the `Radio` that is selected within the `RadioGroup`.
122111 */
123- @Input ( )
124- get value ( ) {
125- return this . _value ;
112+ get selected ( ) {
113+ return this . _selected ;
126114 }
115+
127116 /**
128117 * Sets the value/state of the selected `Radio` within the `RadioGroup` to the passed in value.
129118 */
119+ @Input ( )
130120 set value ( newValue : any ) {
131121 if ( this . _value !== newValue ) {
132122 this . _value = newValue ;
@@ -137,35 +127,31 @@ export class RadioGroup implements OnInit, AfterContentInit, ControlValueAccesso
137127 }
138128
139129 /**
140- * Returns the associated name of the `RadioGroup`.
130+ * Returns the value/state of the selected `Radio` within the `RadioGroup`.
141131 */
142- @Input ( )
143- get name ( ) {
144- return this . _name ;
132+ get value ( ) {
133+ return this . _value ;
145134 }
135+
146136 /**
147137 * Replaces the name associated with the `RadioGroup` with the provided parameter.
148138 */
139+ @Input ( )
149140 set name ( name : string ) {
150141 this . _name = name ;
151142 this . updateRadioNames ( ) ;
152143 }
153-
154144 /**
155- * Returns the disabled value in the `RadioGroup` if there is one .
145+ * Returns the associated name of the `RadioGroup`.
156146 */
157- @Input ( )
158- get disabled ( ) {
159- return this . _disabled ;
147+ get name ( ) {
148+ return this . _name ;
160149 }
150+
161151 /**
162- * Updates the disabled value using the provided parameter and marks the radios to be checked for
163- * changes.
152+ * Set to true to disable the whole radio group
164153 */
165- set disabled ( value ) {
166- this . _disabled = value ;
167- this . markRadiosForCheck ( ) ;
168- }
154+ @Input ( ) disabled = false ;
169155
170156 /**
171157 * Returns the skeleton value in the `RadioGroup` if there is one.
@@ -197,7 +183,7 @@ export class RadioGroup implements OnInit, AfterContentInit, ControlValueAccesso
197183 */
198184 protected _disabled = false ;
199185 /**
200- * Reflects wheather or not the dropdown is loading.
186+ * Reflects whether or not the dropdown is loading.
201187 */
202188 protected _skeleton = false ;
203189 /**
@@ -211,21 +197,14 @@ export class RadioGroup implements OnInit, AfterContentInit, ControlValueAccesso
211197 /**
212198 * The name attribute associated with the `RadioGroup`.
213199 */
214- protected _name = `radio-group-${ RadioGroup . radioGroupCount } ` ;
215-
216- /**
217- * Creates an instance of RadioGroup.
218- */
219- constructor ( protected changeDetectorRef : ChangeDetectorRef , protected elementRef : ElementRef , protected renderer : Renderer2 ) {
220- RadioGroup . radioGroupCount ++ ;
221- }
200+ protected _name = `radio-group-${ RadioGroup . radioGroupCount ++ } ` ;
222201
223202 /**
224203 * Updates the selected `Radio` to be checked (selected).
225204 */
226205 checkSelectedRadio ( ) {
227- if ( this . _selected && ! this . _selected . checked ) {
228- this . _selected . checked = true ;
206+ if ( this . selected && ! this . _selected . checked ) {
207+ this . selected . checked = true ;
229208 }
230209 }
231210
@@ -235,10 +214,9 @@ export class RadioGroup implements OnInit, AfterContentInit, ControlValueAccesso
235214 updateSelectedRadioFromValue ( ) {
236215 let alreadySelected = this . _selected != null && this . _selected . value === this . _value ;
237216
238- if ( this . radios != null && ! alreadySelected ) {
217+ if ( this . radios && ! alreadySelected ) {
239218 this . _selected = null ;
240219 this . radios . forEach ( radio => {
241- radio . checked = this . value === radio . value ;
242220 if ( radio . checked ) {
243221 this . _selected = radio ;
244222 }
@@ -249,31 +227,20 @@ export class RadioGroup implements OnInit, AfterContentInit, ControlValueAccesso
249227 /**
250228 * Creates a class of `RadioChange` to emit the change in the `RadioGroup`.
251229 */
252- emitChangeEvent ( ) {
253- if ( this . isInitialized ) {
254- let event = new RadioChange ( ) ;
255- event . source = this . _selected ;
256- event . value = this . _value ;
257- this . change . emit ( event ) ;
258- }
259- }
260-
261- /**
262- * Calls the `markForCheck()` function within the `changeDetectorRef` class
263- * to trigger Angular's change detection on each radio item.
264- */
265- markRadiosForCheck ( ) {
266- if ( this . radios ) {
267- this . radios . forEach ( radio => radio . markForCheck ( ) ) ;
268- }
230+ emitChangeEvent ( event : RadioChange ) {
231+ this . change . emit ( event ) ;
232+ this . propagateChange ( event . value ) ;
233+ this . onTouched ( ) ;
269234 }
270235
271236 /**
272237 * Synchronizes the names of the radio items with the name of the `RadioGroup`.
273238 */
274239 updateRadioNames ( ) {
275240 if ( this . radios ) {
276- this . radios . forEach ( radio => radio . name = this . name ) ;
241+ setTimeout ( ( ) => {
242+ this . radios . forEach ( radio => radio . name = this . name ) ;
243+ } ) ;
277244 }
278245 }
279246
@@ -282,64 +249,27 @@ export class RadioGroup implements OnInit, AfterContentInit, ControlValueAccesso
282249 */
283250 writeValue ( value : any ) {
284251 this . value = value ;
285- this . changeDetectorRef . markForCheck ( ) ;
286252 }
287253
288- /**
289- * Callback triggered when a `Radio` within the `RadioGroup` is changed.
290- */
291- touch ( ) {
292- if ( this . onTouched ) {
293- this . onTouched ( ) ;
294- }
295- }
296-
297- /**
298- * Builds variant class on the radio items within the `RadioGroup`.
299- */
300- ngOnInit ( ) {
301- // Build variant class
302- const className = `radio${ this . size !== "md" ? `--${ this . size } ` : "" } ` ;
303-
304- // Add class to host element
305- this . renderer . addClass ( this . elementRef . nativeElement , className ) ;
306- }
307-
308- /**
309- * Marks this component as initialized to avoid the initial value getting set by `NgModel` on `RadioGroup`.
310- * This avoids `NgModel` setting the initial value before the OnInit of the `RadioGroup`.
311- */
312254 ngAfterContentInit ( ) {
313- // Mark this component as initialized in AfterContentInit because the initial value can
314- // possibly be set by NgModel on RadioGroup, and it is possible that the OnInit of the
315- // NgModel occurs *after* the OnInit of the RadioGroup.
316- this . isInitialized = true ;
317- this . updateFocusableRadio ( ) ;
318-
319- this . radios . changes . subscribe ( updatedRadios => {
320- this . radios = updatedRadios ;
321- this . updateFocusableRadio ( ) ;
255+ this . radios . changes . subscribe ( ( ) => {
256+ this . updateRadioNames ( ) ;
257+ this . updateRadioChangeHandler ( ) ;
322258 } ) ;
323259
324260 this . updateChildren ( ) ;
261+ this . updateRadioChangeHandler ( ) ;
325262 }
326263
327- updateFocusableRadio ( ) {
328- if ( this . radios && ! this . radios . some ( radio => radio . checked ) ) {
329- this . radios . forEach ( radio => radio . needsToBeFocusable = false ) ;
330- this . radios . first . needsToBeFocusable = true ;
331- this . radios . forEach ( radio => radio . changeDetectorRef . detectChanges ( ) ) ;
332- }
264+ ngAfterViewInit ( ) {
265+ this . updateRadioNames ( ) ;
333266 }
334267
335268 /**
336269 * Used to set method to propagate changes back to the form.
337270 */
338271 public registerOnChange ( fn : any ) {
339- this . propagateChange = value => {
340- this . value = value ;
341- fn ( value ) ;
342- } ;
272+ this . propagateChange = fn ;
343273 }
344274
345275 /**
@@ -362,7 +292,19 @@ export class RadioGroup implements OnInit, AfterContentInit, ControlValueAccesso
362292
363293 protected updateChildren ( ) {
364294 if ( this . radios ) {
365- this . radios . toArray ( ) . forEach ( child => child . skeleton = this . skeleton ) ;
295+ this . radios . forEach ( child => child . skeleton = this . skeleton ) ;
366296 }
367297 }
298+
299+ protected updateRadioChangeHandler ( ) {
300+ this . radios . forEach ( radio => {
301+ radio . registerRadioChangeHandler ( ( event : RadioChange ) => {
302+ // update selected and value from the event
303+ this . _selected = event . source ;
304+ this . _value = event . value ;
305+ // bubble the event
306+ this . emitChangeEvent ( event ) ;
307+ } ) ;
308+ } ) ;
309+ }
368310}
0 commit comments