Advertisement

#10 Rounding Out Our Initial Controls is the Radio Group

In this article we will create a radio group control. For our radio group we will be taking a hands on approach to creating and inserting radio buttons into the DOM. To be able to do this by the end of the article we will have access to the location that we will insert our radio buttons.

We need a template for the radio group

  • WebUi
    • Source
      • forms
        • controls.mixins.pug

We are going to stick with the pattern that we have developed in past articles by first creating a template for our radio group (a). For now we do not have any requirement for the radio group so we will just use the ng-template directive.

controls.mixins.pug (1)

...
mixin radioGroup
    ng-template
...
(a) Adding the template for the radio group.

Define the radio group

  • WebUi
    • Source
      • forms
        • controls
          • radio
            • xc-radio-group.component.pug
            • xc-radio-group.component.scss
            • xc-radio.component.ts

Next we need to define the template (b), the styling (c), and the component definition (d) for the radio group.

xc-radio-group.component.pug (1)

include ../controls.mixins.pug

+formControlGroup
    +radioGroup
(b) Adding the template.

xc-radio-group.component.scss (1)

@import "../controls.mixins.scss";

@include formControlGroup;
(c) Adding the styling.

xc-radio-group.component.ts (1)

import { forwardRef, Component } from "@angular/core";

import { XcFormControl } from "../xc-form-control";
import { XcOptionsFormControl } from "../xc-options-form-control";

@Component({
    selector: "xc-radio-group",
    template: require("./xc-radio-group.component.pug"),
    styles: [require("./xc-radio-group.component.scss")],
    providers: [ { provide: XcFormControl, useExisting: forwardRef(() => XcRadioGroupComponent) } ]
})
export class XcRadioGroupComponent<TValue, TOption> extends XcOptionsFormControl<TValue, TOption> {
    protected get tagName() { return "xc-radio-group"; }
}
(d) Adding the component definition.
Advertisement

Exporting the form group and declaring within our module

  • WebUi
    • Source
      • forms
        • examples
          • form-examples.module.ts
        • controls.index.ts

Once again we have added a new control so we need to export it from our controls index file (e). And now that it is exported we will declare it within our form examples module (f).

controls.index.ts (1)

...
export * from "./radio/xc-radio-group.component";
...
(e) Exporing the radio group from our controls index file.

form-examples.module.ts (1)

...
import {
    ..., XcRadioGroupComponent, ...
} from "./form-examples.index";
...
@NgModule({
    ...,
    declarations: [
        ...,
        XcRadioGroupComponent,
        ...
    ],
    ...
})
export class FormExamplesModule { }
platformBrowserDynamic().bootstrapModule(FormExamplesModule);
(f) Declaring for use within our form examples module.

Time to use the radio group

  • WebUi
    • Source
      • forms
        • examples
          • basic
            • basic-example.component.pug
            • basic-example.component.ts

With the radio group created and declared within our module it is time to use it within our basic example. We start by adding one to the template of the basic example (g). To make our application work we of course then need to update our snippets (h).

basic-example.component.pug (1)

...
div.example-container
    div.example-content
        ...
        div.controls-template-component
            xc-form-group(... )
                +controlRow("radio")
                    xc-radio-group(label="Radio", name="radio", [options]="tOptions" )
                ...
(g) Adding a radio group to our basic example template.

basic-example.component.ts (1)

...
export class BasicExampleComponent implements ... {
    ...
    private readonly _snippets = new SnippetsManager([
        ...
        ["radio", {
            component: `private get tOptions() {
    return [
        { label: "label1", value: "value1" },
        { label: "label2", value: "value2" },
        { label: "label3", value: "value3" },
        { label: "label4", value: "value4" }
    ];
}`,
            template: 'xc-radio-group(label="Radio", name="radio", [options]="tOptions" )'
        }],
        ...
    ]);
    ...
}
(h) Adding the corresponding snippet to our basic example component.

Where are we going to add the radio buttons

  • WebUi
    • Source
      • forms
        • controls
          • radio
            • xc-radio-group.component.ts
          • controls.mixins.pug

In our previous control we used an *ngFor directive to add the options. In this manner we just had to bind our options to the template and angular takes care of the rest. We could take a similar approach here but I have decided we will take a more hands on approach by creating radio buttons and inserting them into the DOM ourselves. Our first order of business is to determine where we will insert the buttons. To do this we return to the template for our radio group and add a template reference variable (i). The next thing we will do is check to see if we are able to get a reference to this element (j). What we see in the console, if we check it, is that our reference is actually undefined. The reason it is undefined is due to the fact that we are using an *ngIf statement which results in the element not actually being present in the DOM until the form group is set on the form control. I did try accessing the element right after the form group is set and of course that still does not work since we need to allow for angular to update the template. The solution that I have decided to use is then to call a method after the view has initialized which will call itself periodically, through the use of a timeout, until the element is available (k).

controls.mixins.pug (2)

...
mixin radioGroup
    ng-template(#radioContainer="")
...
(i) Adding a template reference variable so that we can access the point where we want to insert the radio buttons.

xc-radio-group.component.ts (3)

import { ..., AfterViewInit, ..., ViewChild, ViewContainerRef } from "@angular/core";
...
export class XcRadioGroupComponent ... implements AfterViewInit {
    @ViewChild("radioContainer", { read: ViewContainerRef }) private readonly _radioContainer: ViewContainerRef = null;
    ...
    public ngAfterViewInit(): void {
        console.log(this._radioContainer);
    }
}
(j) Checking to see if we actually have access to the reference. We do not.

xc-radio-group.component.ts (4)

...
export class XcRadioGroupComponent<TValue, TOption> ... {
    ...
    public ngAfterViewInit(): void {
        this.createRadioComponents();
    }

    private createRadioComponents = () => {
        if (typeof this._radioContainer === "undefined") {
            setTimeout(this.createRadioComponents, 100);
            return;
        }

        console.log(this._radioContainer);
    }
}
(k) Using a timeout to call our method recursively until the reference is available.

Now that we have access to the location where our radio buttons will be inserted we need to actually create the buttons that will be inserted. We will take care of this in the next article.

Exciton Interactive LLC
Advertisement