1. Introduction
In this article we are going to present Thymeleaf Input Date component embedded in a Spring Boot application. We will use the Bootstrap framework to create a base template for our responsive website.
For more information about how to configure Thymeleaf for Spring Boot and generally how to use forms check below links:
Spring Boot with Thymeleaf
Thymeleaf Forms
2. Maven dependencies
In this application we will use several libraries:
- org.springframework.boot:spring-boot-starter-web:2.1.5.RELEASE - common Spring Boot dependency,
- org.springframework.boot:spring-boot-starter-thymeleaf:2.1.5.RELEASE - Thymeleaf template engine dependency,
- org.projectlombok:lombok:1.18.2 - library for generating common methods for POJO objects,
- org.webjars:bootstrap:4.0.0-2 - webjar for Bootstrap framework,
- org.webjars:font-awesome:5.11.2 - webjar for Font Awesome Icons,
The Maven pom.xml
file will have the following structure:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>thymeleaf-bootstrap-input-date</artifactId>
<properties>
<bootstrap.version>4.0.0-2</bootstrap.version>
<webjars-locator.version>0.30</webjars-locator.version>
<font-awesome.version>5.11.2</font-awesome.version>
<lombok.version>1.18.2</lombok.version>
</properties>
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
</parent>
<!-- Add typical dependencies for a web application -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>${bootstrap.version}</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
<version>${webjars-locator.version}</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>font-awesome</artifactId>
<version>${font-awesome.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<!-- Package as an executable jar -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3. Model, Controller and Application class
To handle GET and POST requests we defined IndexController
class. The model object User
contains a single field that stores date of birth
. This POJO class is our base command object used in Thymeleaf form to transfer user inputs to the web controller.
package com.frontbackend.thymeleaf.bootstrap.model;
import java.util.Date;
import org.springframework.format.annotation.DateTimeFormat;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Setter
@Getter
@NoArgsConstructor
public class User {
@DateTimeFormat(pattern = "dd/MM/yyyy")
private Date birthdate;
}
package com.frontbackend.thymeleaf.bootstrap.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.frontbackend.thymeleaf.bootstrap.model.User;
@Controller
@RequestMapping({ "/", "/index" })
public class IndexController {
@GetMapping
public String main(Model model) {
model.addAttribute("user", new User());
return "index";
}
@PostMapping
public String save(User user, Model model) {
model.addAttribute("user", user);
return "saved";
}
}
The class Application
contains starting Spring Boot method:
package com.frontbackend.thymeleaf.bootstrap;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
4. Templates
This example application will use two templates:
index.html
- where the main form will be placed,saved.html
- where we present entereddate of birth
.
We used bootstrap-datepicker library for our base date picker
component.
All templates are placed in the default Thymelef folder, which is - /resources/templates
.
The index.html
file will have the following structure:
<!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>Spring Boot Thymeleaf Application - Bootstrap Input Date</title>
<link th:rel="stylesheet" th:href="@{assets/bootstrap-datepicker/css/bootstrap-datepicker.css}"/>
<link th:rel="stylesheet" th:href="@{assets/bootstrap-datepicker/css/bootstrap-datepicker.standalone.css}"/>
<link th:rel="stylesheet" th:href="@{webjars/bootstrap/4.0.0-2/css/bootstrap.min.css} "/>
<link th:rel="stylesheet" th:href="@{webjars/font-awesome/5.11.2/css/all.css} "/>
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark static-top">
<div class="container">
<a class="navbar-brand" href="/">Thymeleaf - Bootstrap Input Date</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home
<span class="sr-only">(current)</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Services</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Contact</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<form method="post" th:object="${user}">
<div class="form-group row">
<div class="col-md-4 mt-5">
<label for="birthdate">Date of birth</label>
<div class="input-group date">
<input type="text" class="form-control" id="birthdate" autocomplete="off" th:field="*{birthdate}"/>
<div class="input-group-append">
<span class="input-group-text"><i class="far fa-calendar-alt"></i></span>
</div>
</div>
</div>
</div>
<button class="btn btn-primary" type="submit">Submit form</button>
</form>
</div>
<script th:src="@{/webjars/jquery/jquery.min.js}"></script>
<script th:src="@{/webjars/popper.js/umd/popper.min.js}"></script>
<script th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
<script th:src="@{assets/bootstrap-datepicker/js/bootstrap-datepicker.js}"></script>
<script>
$('.input-group.date').datepicker({
autoclose: true,
todayHighlight: true
});
</script>
</body>
</html>
The saved.html
file will have the following structure:
<!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>Spring Boot Thymeleaf Application - Bootstrap Input Date</title>
<link th:rel="stylesheet" th:href="@{webjars/bootstrap/4.0.0-2/css/bootstrap.min.css} "/>
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark static-top">
<div class="container">
<a class="navbar-brand" href="/">Thymeleaf - Bootstrap Input Date</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home
<span class="sr-only">(current)</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Services</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Contact</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<h2 class="mt-5">Your date of birth: <strong th:text="${#dates.format(user.birthdate, 'yyyy-MM-dd')}" ></strong></h2>
<a th:href="@{/}" class="btn btn-primary">Go back</a>
</div>
</body>
</html>
As you can see we used #dates utility method to present Date
in the specific format yyyy-MM-dd
.
5. The output
The application works as in the following picture:
6. Conclusion
In this article, we showcased Thymeleaf Input Date component handled by the Spring Boot application and presented using Bootstrap responsive framework.
The full code of this example application is available under our GitHub repository.
{{ 'Comments (%count%)' | trans {count:count} }}
{{ 'Comments are closed.' | trans }}