Form layout in angular web applications

One of the mostly used components in web applications are forms. Thus, it is of prior importance to componentize the layout and the expected behavior of the potentially numerous forms in our applications.

Here there are some common concerns about forms in a web application.

  • Layout between fields and labels.
  • When and where validation messages should appear.
  • Layout of form buttons.

I will try to cover all of the above concerns by presenting an example, keeping in mind all of the tools which angular provides to us.

The problem

Beyond the fact that angular makes our lives easier by providing all those great modules, such as ReactiveFormsModule, it’s our responsibility to keep our code dry and clean by making the right use of them. There are times when forms require lots of inputs, which drives us creating huge and messy templates.

The solution

For that reason we are going to wire up all of those common layout and behavior in components and directives. Let me introduce you those by starting of the inner to outer.

Form error messages

FormErrorMessagesComponent is responsible for rendering the validation messages of the form. Works similarly, to the AngularJS’ ng-messages.

It takes one and only input, the errors of the form.

Form field

FormFieldComponent takes as inputs:

  • the label of the input field
  • the errors to pass them to the FormErrorMessagesComponent.
  • the horizontal or vertical attribute which defines whether the field and the label will be on the same line or not.

Moreover, it projects the input field in its template.

Form buttons

No inputs for this component, which is primarily used for aligning the projected buttons left or right.

Form layout

FormLayoutComponent holds zero business logic and it mainly scopes all the styles which define part of the layout for the rest of the components. That means that it will work as a wrapper for the other components.

Directive handling submit styles class.

SubmittedClassDirective adds css class when form is submitted or removes it when form gets cleared. This will allow us to hide or show the error messages just by css.

The outcome

Putting all those pieces together leads to something like that:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<div class="container-fluid">
<div class="row">
<form
app-form-layout
appSubmittedClass="form-submitted"
[formGroup]="myForm"
(submit)="showForm()"
class="col-4"
>
<app-form-field vertical label="First name" [errors]="myForm.controls.firstName.errors">
<input type="text" formControlName="firstName" />
</app-form-field>

<app-form-field vertical label="Last name" [errors]="myForm.controls.lastName.errors">
<input type="text" formControlName="lastName" />
</app-form-field>

<app-form-field vertical label="Mobile phone" [errors]="myForm.controls.mobilePhone.errors">
<input type="tel" formControlName="mobilePhone" />
</app-form-field>

<app-form-buttons>
<button right type="submit">Submit</button>

<button left type="button" (click)="clearForm()">Clear</button>
</app-form-buttons>
</form>
</div>
</div>

If you would like to dig in here’s the snippet.

Here are some benefits of this approach:

  • Clean markup
  • Dry code

Conclusion

The previously presented example demonstrates some of the capabilities of the angular ecosystem out of which we can benefit when we deal with forms.