Advertisement

#4 Access to the Form Data

In this article we will begin starting to style our application so that it is easier to use. We will also provide access to the data contained within our form group and display it to the user. In the process of doing this we will start using css grid and rxjs.

Pretty up the router outlet

  • WebUi
    • Source
      • forms
        • examples
          • form-examples.component.scss

We will start by adding a bit of styling to our examples container component (a). These changes will adjust the way our main navigation bar looks as well as add a bit of our padding to our router outlet and stretch it vertically to take up the available space.

form-examples.component.scss (1)

$active-color: #303030;

.main-nav {
    position: fixed;
    width: 100%;
    border-bottom: 1px solid lighten($active-color, 25%);
    background-color: white;
    z-index: 1000;

    ul {
        display: flex;
        flex-direction: row;
    }

    a {
        text-decoration: none;
        padding: 0.5em 1em;
        display: block;

        &.active-link {
            background-color: lighten($active-color, 60%);
            color: $active-color;
            font-weight: 600;
        }
    }
}

.router-outlet {
    height: 100%;
    padding: 2.5625em 0 0.5em 0;
}
(a) Time to add a little bit of styling to our main navigation and router outlet.

Form validity, values and errors

  • WebUi
    • Source
      • forms
        • examples
          • basic
            • basic-example.component.ts
        • xc-form-group.component.ts

Next we will add a few more getter properties to our form group component (b). These getters will make it easier to get the data, errors and valid and invalid states of our form group. Now we will make this information available for use within our basic example component's template (c).

Advertisement

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

import { pairs } from "rxjs";
...
import { FormControl, ... } from "@angular/forms";
...
export class XcFormGroupComponent ... {
    ...
    private _data: { [key: string]: any } = {};
    private _errors: { [key: string]: any } = {};
    ...
    public get data() { return this.loopOverControls(this._data, f => { return f.value; }); }
    public get errors() { return this.loopOverControls(this._errors, f => { return f.errors; }); }
    public get group() { return this._group; }
    public get invalid() { return this._group.invalid; }
    public get valid() { return this._group.valid; }
    ...
    private loopOverControls = (o: { [key: string]: any }, func: (fc: FormControl) => any) => {
        const key = (v: [string, FormControl]) => v[0];
        const value = (v: [string, FormControl]) => func(v[1]);

        pairs(this._group.controls)
            .subscribe((x: [string, FormControl]) => o[key(x)]=value(x));

        return o;
    }
}
(b) Exposing several getter properties in our form group component.

basic-example.component.ts (1)

import { ..., ViewChild } from "@angular/core";

import { XcFormGroupComponent } from "../../forms.index";
...
export class BasicExampleComponent {
    @ViewChild("basicFormGroup") private readonly _form: XcFormGroupComponent = null;

    private get tData() { return JSON.stringify(this._form.data, null, 2); }
    private get tErrors() { return JSON.stringify(this._form.errors, null, 2); }
    private get tInvalid() { return this._form.invalid; }
    private get tValid() { return this._form.valid; }
}
(c) Creating more getter properties so that we can display the information to the user.

Time to show the user

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

Our next changes will be to our basic example template so that we display the information that we exposed in the previous section to the user (d). Now that we are showing the information it would be nice to make it look a little bit better so time for some more styling (e).

basic-example.component.pug (2)

div.example-container
    div.example-content
        div.form-data
           div.form-data-heading
                h2 Form
                div.validity.valid(*ngIf="tValid" ) Valid
                div.validity.invalid(*ngIf="tInvalid" ) Invalid
           h3.form-output-heading Data
           div.form-data-output {{tData}}
           hr
           h3.form-output-heading Errors
           div.form-data-output {{tErrors}}
        div.controls-template-component
            xc-form-group(#basicFormGroup="", name="Basic Form Group" )
                div.controls
                    xc-input(label="Input", name="input")
(d) Updating the basic example template to show the information to the user.

basic-example.component.scss (1)

.example-container {
    display: flex;
    height: 100%;
}

.example-content {
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-areas: "form-data controls";
    flex: 1;
}

$gutter: 0.25em;
$form-data-width: 13em;
$form-data-background-color: white;
$form-data-border-color: gray;

.form-data {
    grid-area: form-data;
    width: $form-data-width + 2*$gutter;
    border-right: 1px solid $form-data-border-color;
    background-color: $form-data-background-color;
    padding: $gutter;

    .form-data-heading {
        border-bottom: 1px solid $form-data-border-color;
        display: flex;
        flex-direction: row;
        align-items: center;
        padding-bottom: 0.25em;
        margin-bottom: 1.5em;

        h2 {
            flex: 1;
            margin: 0;
        }

        .validity {
            padding: 0.25em;
            color: white;
            width: 3.5em;
            text-align: center;

            &.valid {
                background-color: #34a934
            }

            &.invalid {
                background-color: #9a2a2a;
            }
        }
    }

    .form-output-heading {
        margin: 0;
        font-size: 1.15em;
    }

    .form-data-output {
        background-color: $form-data-background-color;
        border: none;
        box-shadow: none;
        overflow: auto;
        white-space: pre;
        margin-bottom: 0.25em;
    }
}

.controls {
    grid-area: controls;
    padding: $gutter;
}
(e) Adding a little styling to make the information a little easier to understand.
Exciton Interactive LLC
Advertisement