#4 Access to the Form Data
Friday, June 29, 2018
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.
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
Pretty up the router outlet
-
WebUi
-
Source
-
forms
-
examples
- form-examples.component.scss
-
examples
-
forms
-
Source
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;
}
Form validity, values and errors
-
WebUi
-
Source
-
forms
-
examples
-
basic
- basic-example.component.ts
-
basic
- xc-form-group.component.ts
-
examples
-
forms
-
Source
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).
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;
}
}
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; }
}
Time to show the user
-
WebUi
-
Source
-
forms
-
examples
-
basic
- basic-example.component.pug
- basic-example.component.scss
-
basic
-
examples
-
forms
-
Source
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")
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;
}