#10 Rounding Out Our Initial Controls is the Radio Group
Friday, September 14, 2018
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.
Parts
- Part 14: Pipes to the Rescue
- Part 13: Rest of the Examples
- Part 12: Checkbox Example
- Part 11: Adding a Radio Button
- Part 10: Adding a Radio Group
- Part 9: Adding a Select
- Part 8: Adding a Checkbox
- Part 7: Adding a Textarea
- Part 6: Highlighting with Prismjs
- Part 5: Form Snippets Manager
- Part 4: Accessing Form Data
- Part 3: Angular Form Group Interop
- Part 2: The Form Group
- Part 1: Forms Project Creation
We need a template for the radio group
-
WebUi
-
Source
-
forms
- controls.mixins.pug
-
forms
-
Source
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
...
Define the radio group
-
WebUi
-
Source
-
forms
-
controls
-
radio
- xc-radio-group.component.pug
- xc-radio-group.component.scss
- xc-radio.component.ts
-
radio
-
controls
-
forms
-
Source
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
xc-radio-group.component.scss (1)
@import "../controls.mixins.scss";
@include formControlGroup;
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"; }
}
Exporting the form group and declaring within our module
-
WebUi
-
Source
-
forms
-
examples
- form-examples.module.ts
- controls.index.ts
-
examples
-
forms
-
Source
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";
...
form-examples.module.ts (1)
...
import {
..., XcRadioGroupComponent, ...
} from "./form-examples.index";
...
@NgModule({
...,
declarations: [
...,
XcRadioGroupComponent,
...
],
...
})
export class FormExamplesModule { }
platformBrowserDynamic().bootstrapModule(FormExamplesModule);
Time to use the radio group
-
WebUi
-
Source
-
forms
-
examples
-
basic
- basic-example.component.pug
- basic-example.component.ts
-
basic
-
examples
-
forms
-
Source
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" )
...
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" )'
}],
...
]);
...
}
Where are we going to add the radio buttons
-
WebUi
-
Source
-
forms
-
controls
-
radio
- xc-radio-group.component.ts
- controls.mixins.pug
-
radio
-
controls
-
forms
-
Source
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="")
...
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);
}
}
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);
}
}
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.