The news

Build a reusable validation component for angular shapes

Form validation is an essential aspect of web development, especially when building applications with Angular. It ensures that the user enters data in the correct format, helping to avoid errors and improve the overall user experience.

When creating forms in Angular, it's important to provide feedback to the user on any errors in the form. This feedback can take the form of error messages that appear next to form controls when the user has entered invalid data.

The benefits of implementing a reusable validation message solution

Having a generic solution for displaying validation messages is important because it allows developers to write reusable code that can be applied to any form control, instead of having to write separate code for each individual form control. This reduces the amount of code to be written, making the development process more efficient and scalable. A generic solution also makes it easier to maintain and update the code base, as changes can be made in a single place, rather than having to update several components.

Simple form validation

In this section, we'll look at a simple example of a form requiring validation. Let's say we have a registration form that asks users to provide their name, e-mail address and password. Without a reusable validation component, we would typically add validation to this form as follows

We start by declaring a FormGroupusing the reactive forms approach in Angular (in this example, we're using a standalone component)

https://medium.com/media/b97600169ccc09eb9496a1a7630083de

In our example, we import the necessary module [ReactiveFormsModule] from @angular/formsthe creation of a FormGroupinstance with its controls. Visit FormGroupis used to group together a set of FormControlinstances, each representing a form entry.

To create a FormControlIn this case, you pass a default value as the first argument and an array of validators as the second argument. The validators are used to validate the input value.

For example, you can use :

  • Validators.requiredvalidator to make the required entry
  • Validators.emailto validate entry as e-mail
  • or you can create your own custom synchronous or asynchronous validator

In the component model, you link the inputs to their respective controls using the formControlNamedirective. To display error messages, you can use the ngIfdirective and access the validity of controls using the getmethod FormGroupinstance.

In the model, we use Angular's built-in directives to display validation error messages according to the validation rules declared in the component's TypeScript code. The formControlNamedirective is used to link the input element to a form control, while the ngIfis used to show or hide the error message depending on the validity of the form control.

https://medium.com/media/01ddcaf36299f4164f91caa124c70c98

In this code, we'll look at a common problem in Angular's reactive forms, the duplication of validation logic in the model. This approach can lead to repetitive and error-prone code, so we'll explore a better way of implementing form validation in Angular.

This approach can quickly become cumbersome, especially if the form contains many fields. What's more, implementing validation in the model can complicate the management of validation rules and the display of error messages, as well as increasing the risk of errors.

Reusable component validation message

To solve the problem with classic validation, we can centralize the validation logic in a reusable component and reuse it for each form field. This approach facilitates the management of validation rules and the display of error messages, improves code maintainability and reduces the risk of errors.

we start by creating a standalone component (you can't use any standalone component) to handle form validation messages. This component takes a form control as input and displays error messages based on existing errors in the form control.

  • Create a new ErrorMessage component
ng gc error messages --standalone

CREATE src /app/error-message/error-message .component .scss ( 0 bytes)
CREATE src /app/error-message/error-message .component .html ( 28 bytes)
CREATE src /app/error-message/error-message .component .spec .ts ( 637 bytes)
CREATE src /app/error-message/error-message .component .ts ( 398 bytes)
  • This component requires a AbstractControlto manage validation
https://medium.com/media/f33c4149e843b9766923705f53fd0c16
  • Create a TypeScript file ( validators-utils.ts ) that includes a list of messages displayed according to error type, and a function to manage them
https://medium.com/media/1b266a4528051f9505382240becae711validateur-utils.ts

stringFormatis a function that takes a string template as its first argument and a list of variable arguments. The function replaces occurrences of {x}in the template by the corresponding argument in the list. If the argument to the specified index is not defined, the original {x}is left in the chain.

ValidationErrors: defines the error map returned by failed validation checks.

messagesis a constant Map object that associates validator names with their error messages and the validator's error key. Error messages can include placeholders in the form of {x}will be replaced by the corresponding arguments passed to stringFormat.

validatorErrorsKeyis a validator error table. These tables are used to extract the necessary values from the validatorErrorsobject to be transmitted as arguments to stringFormat.

getValidatorErrorMessageis a function that takes two arguments, validatorNameand validatorErrors. The function first retrieves the object ( {message : string,validatorErrorsKey? : string[]} ) associated with the validator's name from the messagescard.

It then recovers the values of validator errors, then uses them stringFormatto format the error message associated with the validator name from the messagescard. If there are no parameters associated with the validator name, the function simply returns the error message.

For example, if we have a Validator.minLength(8)and we break this rule by typing only 5 characters, then :

validatorName = minlength 
validatorErrors = { 'actualLength' : 5 , 'requiredLength' : 8 }
  • To integrate the exported function getValidatorErrorMessagein the ErrorMessageComponentfunction to display error messages. To do this, simply import the function into the component file, then call the function, passing it the necessary parameters such as validatorNameand validatorErrors. The returned string can then be used as an error message.
https://medium.com/media/ac7bfc3cf91f96badd6b828f641a8e20
  • Now it's time to use our reusable validation component in our forms. To use our component, we need to import it and simply use it in our model.
https://medium.com/media/a02b1990ab208965140cec4c968bce5a
  • and in the
https://medium.com/media/12b56e1d278dccee3b7b402d99b37806

Now we have our reusable component and it clearly provides a clean and simple solution for form validation. It eliminates the potential for errors that are often present in traditional validation methods, making it easier for developers and maintainers to use.

No reusable components
With reusable component

Reusable component validation message with Angular Material

Now let's learn how to integrate our component with Angular Material. We'll be using MatFormFieldModulewith mat-errorto display messages. The problem mat-erroris that it must be used directly in mat-form-field.To overcome this, we need to use our reusable component as an attribute, not as an element. This is achieved by using it as an attribute of the mat-error.

  • To use a selector as an attribute, we can use square brackets [ ]in the selector declaration
@Component({Composant ({ 
selector : '[app-error-message]' ,
standalone : true ,
imports : [CommonModule],
template : `<ng-container *ngIf= "errorMessage !== null" >{{errorMessage}}
</ ng-container>`,
}) classe
d'exportation ErrorMessageComponent
  • and now we can use our component in mat-error (don't forget to import MatFormFieldModule and MatInputModule)
https://medium.com/media/a01146d8e0de2a22db998d7b679b0808

Summary

In this article, we discovered the benefits of using reusable components for form validation in Angular and how to implement it. This approach leads to more manageable code and reduces the risk of errors by reusing validation logic.

You can find the code here, I use an application based on standalone components. You can read more about it in this article.

If you have any questions or comments, please let me know in the comments below.

To learn more about Angular, JS and Java, you can follow me on Medium or Twitter.