# Validation

Validating user entered data is usually required both on the client-side and on the server-side, often causing a violation of the DRY (opens new window) design principle. With Remult, validation code can be placed within the entity class, and Remult will run the validation logic on both the frontend and the relevant API requests.

# Validate the Title Field

Task titles are required. Let's add a validity check for this rule, and display an appropriate error message in the UI.

  1. In the Task entity class, modify the Fields.string decorator for the title field to include an object literal argument and set the object's validate property to Validators.required.

src/shared/Task.ts

 
 
 


@Fields.string({
    validate: Validators.required
})
title = '';

Import Validators

This code requires adding an import of Validators from remult.

  1. In the App.vue template, modify the saveTask function to catch exceptions.

src/App.vue


 


 
 
 


async function saveTask(task: Task) {
  try {
    const savedTask = await taskRepo.save(task);
    tasks.value = tasks.value.map(t => t === task ? savedTask : t);
  } catch (error: any) {
    alert(error.message);
  }
}

Manual refresh required

For this change to take effect, you must manually refresh the browser.

After the browser is refreshed, try creating a new task or saving an existing one with an empty title - the "Should not be empty" error message is displayed.

# Implicit server-side validation

The validation code we've added is called by Remult on the server-side to validate any API calls attempting to modify the title field.

Try making the following POST http request to the http://localhost:3002/api/tasks API route, providing an invalid title.

curl -i http://localhost:3002/api/tasks -H "Content-Type: application/json" -d "{\"title\": \"\"}"

An http error is returned and the validation error text is included in the response body,

# Custom Validation

The validate property of the first argument of Remult field decorators can be set to an arrow function which will be called to validate input on both front-end and back-end.

Try something like this and see what happens:

src/shared/Task.ts

@Fields.string<Task>({
    validate: (task) => {
        if (task.title.length < 3)
            throw "Too Short";
    }
})
title = '';