1. Introduction
In this article, we are going to present the Thymeleaf Modal component based on the Bootstrap framework and Spring Boot application server. We will make a use of Thymeleaf Fragments to create injectable piece of HTML document that will contain a modal code.
If you are looking for more useful articles about Thymeleaf, please check the following links:
Thymeleaf Article List
Building forms with Thymeleaf
2. Dependencies
2.1. Maven dependencies
To present how the Thymeleaf Modal component works with Thymeleaf we used a simple Spring Boot application created as a Maven project with the following dependencies:
2.2. Front-End libraries
bootstrap - a frontend framework for creating responsive websites.
Project Maven pom.xml
file has the following structure:
Copy
<?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-modal</artifactId>
<properties>
<bootstrap.version>4.0.0-2</bootstrap.version>
<webjars-locator.version>0.30</webjars-locator.version>
<lombok.version>1.18.2</lombok.version>
<commonmark.version>0.13.1</commonmark.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.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. Web Controller and Main Application class
The main controller that serves index.html
template on the root context is called: IndexController
:
Copy
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.RequestMapping;
@Controller
@RequestMapping("/")
public class IndexController {
@GetMapping
public String main(Model model) {
return "index";
}
}
To show how to create modals with dynamic content we used ModalController
that handles GET requests to /modals/modal1
and /modals/modal2
path:
Copy
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.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("modals")
public class ModalController {
@GetMapping("modal1")
public String modal1() {
return "modal1";
}
@GetMapping("modal2")
public String modal2(@RequestParam("name") String name, Model model) {
model.addAttribute("name", name);
return "modal2";
}
}
The Application
is the Java class with the main method that starts the Spring Boot application server:
Copy
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
In the presentation layer we have several Thymeleaf templates:
index.html - the main view with buttons to fire modals,
modal1.html - content for modal 1,
modal1.html - content for modal 2,
_modals.html - HTML with Thymeleaf fragment code.
The index.html
template has the following structure:
Copy
<!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>Spring Boot Thymeleaf Application - Bootstrap Modal</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 Modal</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">
<div class="row mt-5">
<div class="col">
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
Launch simple modal
</button>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal1">
Dynamic modal 1
</button>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal2">
Dynamic modal 2
</button>
<th:block th:replace="_modals :: modal('exampleModal')">modal</th:block>
<th:block th:replace="_modals :: modal('exampleModal1')">modal</th:block>
<th:block th:replace="_modals :: modal('exampleModal2')">modal</th:block>
</div>
</div>
</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>
$('#exampleModal1').on('show.bs.modal', function () {
$.get("/modals/modal1", function (data) {
$('#exampleModal1').find('.modal-body').html(data);
})
});
$('#exampleModal2').on('show.bs.modal', function () {
var name = prompt("Please enter your name", "John Doe");
$.get("/modals/modal2?name=" + name, function (data) {
$('#exampleModal2').find('.modal-body').html(data);
})
})
</script>
</body>
</html>
modal1.html
- contains a simple text content:
Copy
Dynamic content for Modal 1
modal2.html
- contains sample Thymeleaf attribute that will display a name user prompt:
Copy
Hello <strong th:text="${name}"></strong>! Nice to see you.
_modals.html
- contains fragment with Bootstrap modal code:
Copy
<!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
</head>
<body>
<!-- Modal -->
<div th:fragment="modal(id)" class="modal fade" th:id="${id}" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in,
egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</body>
</html>
5. The output
The running application is available under http://locahost:8080
URL and presents the following functionality:
6. Conclusion
In this article, we showcased how to use Bootstrap Modal in Thymeleaf templates. We used fragments to separate HTML code required for generating modal.
As usual, the code used in this article is available under our GitHub repository
{{ 'Comments (%count%)' | trans {count:count} }}
{{ 'Comments are closed.' | trans }}