_ Blog / Technology

Angular Form Handling: Useful Techniques, Practices and Examples

by László Csele `Lacka`
/ June 10, 2021
#Technology
Angular Form

In our latest project, we were facing some form-handling challenges. This post aims to decompose this issue and to show you our most used form-handling techniques. I hope these will help you make form handling with Angular much easier.

The basics

If I need to create forms, I prefer to use Angular’s Reactive Forms Module, which is quite self-explanatory in most cases.

The base building blocks are the following:

  • Form controls (a single form input handler)
  • Form groups (for grouping form controls)
  • Form arrays (help us creating a variable number of form controls)
  • Validators

There are two different types of forms in the application: one with a submit button and one with auto-save functionality. I will show you the differences from a UX perspective and why we do it this way.

Simple Angular form with submit button

In this type of form, every input has a clean appearance in the beginning. The main question is: When should we inform the user if the filing contains an error?

If you display all the errors initially, the user can get frustrated, so that’s not an option. In this case, we try to follow the following rules:

  • No error message displayed at first
  • Error is displayed after a user has interacted with an input field and tried to move forward with a missing or an invalid value
  • Error is shown when the user tries to submit the form
  • Submission only works when the form is correct
  • You should disable the submit button until the previous submission is in progress

The application will provide clear information to the user about what is wrong with the form, for example, there is a red border around the input fields and an error message below the fields. Once the input is corrected, the notification disappears.

Angular form with auto-save functionality

The rules from the previous example don’t work well in this situation since there aren’t any submit buttons that we can click to trigger the validation messages.

You also shouldn’t block the auto-save functionality until the form is filled out correctly.

Imagine you have a form with 60 required fields, and you’ve filled out the first 50 when the browser crashes. When the user returns to the process, all the previous data should be available. So the rules are as follows:

  • All error messages should be displayed until it’s not correct but not showing a red border.
  • If the user touched or clicked the input but didn’t fill it out correctly, a red border should be displayed.
  • The auto-save functionality should not be blocked.
  • The next steps of the application might need to be blocked until the form is filled out correctly.

Here is a simple auto-save functionality in Angular:

formGroup = this._fb.group({
    name: ["", [Validators.required]]
  });
 
  constructor(private _fb: FormBuilder) {}
 
  ngOnInit() {
    this.formGroup.valueChanges
      .pipe(
        takeUntil(this._destroy$),
        debounceTime(500),
        concatMap(value => this.fakeSave(value)),
        tap(console.log)
      )
      .subscribe();
  }
 
  fakeSave(value) {
    return of(`Saved: ${JSON.stringify(value)}`).pipe(
      tap(() => console.log("started")),
      delay(1000)
    );
  }

Common rules

There are some similarities in these two ways of form handling:

  • Required fields are always marked in some way, e.g., a red star after the input’s label.
  • The red border around the input isn’t shown before the user touches that field.
  • Use descriptive error messages under the fields.
  • Notify users about unsuccessful form submissions.

I hope following these rules can help everyone achieve a better, more consistent user experience in their applications. If you don’t follow the same rules, the most important thing is, BE CONSISTENT across the entire application. This will help the user understand what mistakes they made and understand how to fix that.

The full example repo is available at stackblitz.io.