0
votes

In my UI I'm having trouble with radiobuttons in Angular2+ (Angular 7). I'm trying to set a FormGroup to disabled based on a radiobutton sibling FormControl.

Here's the constraints I have to work with.

  • There are 2 sets of options the user is allowed to select from.
  • Any combination of options is allowed within the same set
  • Selecting options within 2 sets at the same time is not allowed
  • The form should be created as dynamically as possible from a json api

Example:

  • Legal selection:

    SetA:{ "male":true , "female":false } , SetB:{"cat":false,"dog":false"}

  • Illegal selection:

    SetA:{"male":true , "female":false } , SetB:{"cat":true,"dog":false"}

My approach:

I thought I would have a radiobutton for each set heading and disable child item selection when the radiobutton is not selected, then use code do set the any child items to false when the form is submitted.

I'm trying to use reactive forms, but that's not a requirement.

I'm open to any redesign, the only set in stone requirement is no selecting from 2 or more categories simultaniously. In future there may be more mutually exclusive sets.

The current UI which I have to re-implement in Angular just uses all checkboxes and pops an alert complaining if the user tries to submit an invalid selection. I'm hoping to do better.

Problem

When I subscribe to the formcontrol of the radiobutton, the control value printed by my subscribe function is always "undefined".

Code

constructor( private fb: FormBuilder ) { }

ngOnInit( ) {
    const fb = this.fb;
    this.selectionForm = fb.group({
        type2: fb.array([

            fb.group({
                // I'm using this control to store the label
                char: new FormControl('gender') ,

                // This one is the radiobutton
                charSelected:new FormControl(false),

                // these should be disabled unless charSelected=true
                vals: fb.group({
                    male: new FormControl(false),
                    female: new FormControl(false)
                })
            }),

            fb.group({

                char: new FormControl('species') ,

                //radiobutton
                charSelected:new FormControl(''),

                vals: fb.group({
                    cat: new FormControl(false),
                    dog: new FormControl(false)
                })
            })

        ])
    });
}


public getTypeArray( typeName ){
    return <FormArray>this.selectionForm.get(typeName);
}

public getGroupKeys( typeName , index ){
    const type = <FormGroup>this.selectionForm.get([typeName,index,'vals']);
    const keys = Object.keys(type.controls);
    return keys;
}

public getLabel( typeName, index ){
    const char = <FormControl>this.selectionForm.get([typeName,index,'char']);
    return char.value;
}


// I was expecting to get True/False form this, but it comes back undefined
public subscribeParentSelected(  control: FormControl ){
    control.valueChanges.subscribe( val=>{
        console.log( control.value );
        console.log( val );
    });
}

Template

<div formArrayName="type2" class= "row">
                        <ng-container *ngFor="let a of getTypeArray('type2').controls; let i=index">
                            <div [formGroupName]="i" class="col">

                                <input formControlName="charSelected" type="radio" name="charSelected" (change)="changedRadio($event);">


                                <!-- 
<select formControlName="charSelected">
                                    <option *ngFor="let c of "
                                </select>

                                    <input formControlName="charSelected" type="radio" name="charSelected" (change)="changedRadio($event);">
                                -->
                                <b>{{ getLabel('type2',i) | titlecase }}</b>

                                <div formGroupName="vals" style="margin-left:20px;">
                                    <ng-container *ngFor="let d of getGroupKeys('type2',i);">
                                        <input [formControlName]="d" type="checkbox">{{d}}<br>
                                    </ng-container>
                                </div>                              
                            </div>
                        </ng-container>                     

Angular info

    "@angular-devkit/architect": "0.13.0",
    "@angular-devkit/build-optimizer": "0.13.0",
    "@angular-devkit/build-webpack": "0.13.0",
    "@angular-devkit/core": "7.3.0",
    "@ngtools/webpack": "7.3.0",
1

1 Answers

0
votes

I re-organized the form structure, bound a value to the formgroup, and added a function to check the form state to set things disabled.

<input formControlName="selected" type="radio" value="{{ddChar.characteristic}}" (change)="updateType2()">