Simple Spring Boot CRUD application with Client-side form validation
This post describes how to add client-side form validation to an existing Spring Boot web application. The example code uses Thymeleaf Template Engine, Bootstrap 3 and Spring JPA in conjunction with HSQL DB.
Introduction
The example code is based on the previous post that described how to set up simple Spring Boot CRUD application.
This time we add client-side form validation to the existing web application. As we already use jQuery in the context of Bootstrap 3, we are going to add the jQuery validation plugin, which can be downloaded from here. Additionally, we are going to customize the plugin to support the way Bootstrap displays form errors.
Validation Rules
The existing application already allows you to to create, read, update and delete notes. The notes object consists of the following attributes:
- id: the unique id of a notes object
- title: the title of the notes (required, minimum length 5 and maximum length 100 characters)
- content: the actual content of the notes (required, minimum length 8 and maximum length 10,000 characters)
Where is the code?
The code for this post is available in this GitHub repository
Implementation
Edit View: add the validation rules
First, we have to add the following two additional JavaScript files:
- jquery.validate.min.js: the validation plugin
- jquery.validate.bootstrap.js: the validation plugin extension to support Bootstrap (described in the next section)
To activate the form validation in the next step we have to ensure to add an id to the form element.id="notesForm"
This allows us to easily select the correct form HTML element and to attach validation.
Finally, we add a JavaScript block to define the rules, custom messaged and activate validation.
It usually is a good idea to wrap the code into a $(document).ready(function () { ... }
block to ensure that the document has been fully loaded before referencing elements on the page.
We activate validation for our form using.$("#notesForm").validate( options )
The options object includes two main areas:
Rules
We are going to specify all validation rules using a JSON object. This is quite easy and self-explaining. We only have to use the id of the form input element and add the validation rules. The example below shows the validation rules, based on our requirements described in the first section.
rules: {
'title': {
required: true,
minlength: 5,
maxlength: 100
},
'content': {
required: true,
minlength: 8,
maxlength: 10000
}
}
Optional: Custom messages
The validation plugin provides for all validation rules default messages, even for different languages if you include the corresponding localization files. We want to add a custom message for the required rule of the title element. It is the same idea as for the rules specification. We only have to use the form input element as a key and add the messages for each validation rule we want to customize.
messages: {
title: {
required: "Please enter the title!"
}
}
The final HTML file that includes all required changes is below.
NotesEdit.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Notes</title>
<link rel="stylesheet" type="text/css" media="all" href="../../css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" />
<script type="text/javascript" th:src="@{/js/jquery.min.js}" src="js/jquery.min.js"></script>
<script type="text/javascript" th:src="@{/js/bootstrap.min.js}" src="js/bootstrap.min.js"></script>
<!-- include the jQuery validation plugin -->
<script type="text/javascript" th:src="@{/js/jquery.validate.min.js}" src="js/jquery.validate.min.js"></script>
<!-- add the required customizations for Bootstrap -->
<script type="text/javascript" th:src="@{/js/jquery.validate.bootstrap.js}" src="js/jquery.validate.bootstrap.js"></script>
</head>
<body>
<div class="container">
<h1>Notes</h1>
<form id="notesForm" class="form-group" action="/notesEdit" th:action="@{/notesEdit}" method="post">
<input th:type="hidden" name="id" th:field="${notes.id}" />
<div class="form-group">
<label for="title">Title</label>
<input type="text" class="form-control" id="title" th:field="${notes.title}" />
</div>
<div class="form-group">
<label for="content">Content</label>
<textarea class="form-control" id="content" th:field="${notes.content}"></textarea>
</div>
<button type="submit" class="btn btn-primary">Save</button>
<a href="#" th:href="@{/}" class="btn btn-danger" role="button">Cancel</a>
</form>
</div>
<!-- define validation rules and activate validation -->
<script>
$(document).ready(function () {
$("#notesForm").validate({
rules: {
'title': {
required: true,
minlength: 5,
maxlength: 100
},
'content': {
required: true,
minlength: 8,
maxlength: 10000
}
},
messages: {
title: {
required: "Please enter the title!"
}
}
});
});
</script>
</body>
</html>
Customize jQuery validation plugin
The jQuery validation plugin is a UI framework neutral solution to validate HTML forms. As we use Bootstrap for the user interface, we want to use Bootstrap's look and feel for validation and error handling as well. We can achieve this by customizing the jQuery plugin.
The solution below was introduced in this Stackoverflow post.
The basic idea is to overwrite the following methods from the validation plugin:
- highlight: Is being invoked when a validation error was discovered for a specific form input element. We simply add the "has-error" class and remove the "has-success" class.
- unhighlight: Is being invoked when a no validation error was discovered for a specific form input element.
- errorPlacement: Specifies how and where to place the error text for each form input element.
jquery.validate.bootstrap.js
jQuery.validator.setDefaults({
errorElement: "span",
errorClass: "help-block",
// Style the HTML element in case of validation errors
highlight: function (element, errorClass, validClass) {
if (!$(element).hasClass('novalidation')) {
$(element).closest('.form-group').removeClass('has-success').addClass('has-error');
}
},
// Style the HTML element in case of validation success
unhighlight: function (element, errorClass, validClass) {
if (!$(element).hasClass('novalidation')) {
$(element).closest('.form-group').removeClass('has-error').addClass('has-success');
}
},
// Place the error text for different input element types
errorPlacement: function (error, element) {
if (element.parent('.input-group').length) {
error.insertAfter(element.parent());
}
else if (element.prop('type') === 'radio' && element.parent('.radio-inline').length) {
error.insertAfter(element.parent().parent());
}
else if (element.prop('type') === 'checkbox' || element.prop('type') === 'radio') {
error.appendTo(element.parent().parent());
}
else {
error.insertAfter(element);
}
}
});
// Reference: https://stackoverflow.com/questions/18754020/bootstrap-3-with-jquery-validation-plugin
Start and test the application
We can now start the application either from the IDE or from the command line.
Command Line
We can use
mvn package
to build the application from the command line and
java -jar target/CrudClientValidationApp-1.0-SNAPSHOT.jar
to start the application.
Test the application
After starting up we can access the application using this URL: localhost:8090
The screenshot below show how the form looks like when validation errors occur.
Summary
Implementing client-side server validation using jQuery validation plugin with minor customization provides an easy way to improve the user experience by providing fast feedback on validation error without the requirement to go through a server round-trip.
Code on GitHub
The code for this example is available in this GitHub repository
Tags
AOP Apache Kafka Bootstrap Go Java Linux MongoDB Nginx Security Spring Spring Boot Spring Security SSL ThymeleafSearch
Archive
- 1 December 2023
- 1 November 2023
- 1 May 2019
- 2 April 2019
- 1 May 2018
- 1 April 2018
- 1 March 2018
- 2 February 2018
- 1 January 2018
- 5 December 2017
- 7 November 2017
- 2 October 2017