Spring Boot + Bootstrap + Thymeleaf Countdown

March 08, 2020 No comments Spring Boot Bootstrap Thymeleaf Countdown

Spring Boot + Bootstrap + Thymeleaf Countdown

1. Introduction

In this article, we are going to present Thymeleaf Countdown component that could be used for many different purposes. The most common use of countdowns is to show your audience when the website, that is under construction right now, will be ready and accessible.

For more articles about Thymeleaf visit below link:
Thymeleaf Tutorial

2. Dependencies

2.1. Maven dependencies

The sample application, used to present Countdown component, has three main Maven dependencies:

  • springframework - common Spring dependency,
  • thymeleaf - Thymeleaf template engine dependency,
  • lombok - library for generating common methods (like setters and getters) and various constructors in POJO classes.
2.2. Front-End libraries
  • bootstrap - a framework for creating responsive websites.
  • jquery-countdown - a JavaScript library for creating countdown components.

Maven pom.xml file 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-countdown</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>
        <font-awesome.version>5.11.2</font-awesome.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. Controller and Main Application class

The application will use a single Web Controller that serves index.html template on the root context. Every GET request to the main application path / will return rendered index.html page.

IndexController class has the following structure:

package com.frontbackend.thymeleaf.bootstrap.controller;

import java.text.ParseException;
import java.text.SimpleDateFormat;

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) throws ParseException {
        model.addAttribute("endDate", new SimpleDateFormat("yyyy-MM-dd").parse("2022-01-01"));
        return "index";
    }
}

The endDate attributes hold the date to which the countdown component will count down.

The Application is the Java class with the main method that starts the Spring Boot application server:

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 one template - index.html - where the countdown component is placed.

The index.html template has 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 Countdown</title>

    <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} "/>
    <link th:rel="stylesheet" th:href="@{/assets/styles/custom.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 Countdown</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">
        <div class="col-lg-8 mt-5">
            <div class="rounded bg-gradient text-white shadow p-5 text-center mb-5">
                <p class="mb-0 font-weight-bold text-uppercase">We'll open in</p>
                <div id="clock" class="countdown pt-4"></div>
            </div>
        </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 th:src="@{/assets/jquery-countdown/jquery.countdown.min.js}"></script>

<script th:inline="javascript">
    var endDate = [[${#calendars.format(endDate,'yyyy/MM/dd')}]];

    $('#clock').countdown(endDate).on('update.countdown', function (event) {
        var $this = $(this).html(event.strftime(''
            + '<span class="h1 font-weight-bold">%D</span> Day%!d'
            + '<span class="h1 font-weight-bold">%H</span> Hr'
            + '<span class="h1 font-weight-bold">%M</span> Min'
            + '<span class="h1 font-weight-bold">%S</span> Sec'));
    });
</script>

</body>
</html>

We set a JavaScript variable in Thymeleaf template using Java object to define the endDate parameter of the countdown component.

To build countdown component we used external jquery library: http://hilios.github.io/jQuery.countdown that is available under MIT licence.

The initialization of jquery-countdown plugin looks like the following:

 var endDate = [[${#calendars.format(endDate,'yyyy/MM/dd')}]];

    $('#clock').countdown(endDate).on('update.countdown', function (event) {
        var $this = $(this).html(event.strftime(''
            + '<span class="h1 font-weight-bold">%D</span> Day%!d'
            + '<span class="h1 font-weight-bold">%H</span> Hr'
            + '<span class="h1 font-weight-bold">%M</span> Min'
            + '<span class="h1 font-weight-bold">%S</span> Sec'));
    });

5. The output

The running application is available under http://locahost:8080 URL and presents the following functionality:

Thymeleaf bootstrap countdown

6. Conclusion

In this article, we presented Thymeleaf Countdown component. This kind of GUI element is commonly used to show that the site needs some time to be finished and will be available in a specific time.

As usual, the code used in this article is available under our GitHub repository.

{{ message }}

{{ 'Comments are closed.' | trans }}