Spring Boot + Bootstrap + Thymeleaf Telephone Input

July 06, 2020 No comments Spring Boot Bootstrap Thymeleaf Input Telephone

Spring Boot + Bootstrap + Thymeleaf Input Telephone Number

1. Introduction

In this article, we are going to present Thymeleaf Input Telephone Number component. The input will automatically select flag when we enter country code in telephone number.

You can find more information about Thymeleaf and Forms in the following links:
Thymeleaf Articles
Forms in Thymeleaf

2. Dependencies

2.1. Maven dependencies

To show how Telephone Input component works, we used a sample Spring Boot application created as a Maven project using three main dependencies:

2.2. Front-End libraries
  • bootstrap - a frontend framework for creating responsive websites,
  • intl-tel-input - JS library for custom telephone number inputs.

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-telephone-input</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. Model, Controller, and Main Application class

In the model layer we have a single object Address with a field tel to simulate entering customer address data.

package com.frontbackend.thymeleaf.bootstrap.model;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Setter
@Getter
@NoArgsConstructor
public class Address {

    private String tel;

}

GET requests to the root context are handled by Spring Web Controller:

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.Address;

@Controller
@RequestMapping({ "/", "/index" })
public class IndexController {

    @GetMapping
    public String main(Model model) {
        model.addAttribute("address", new Address());
        return "index";
    }

    @PostMapping
    public String save(Address address, Model model) {
        model.addAttribute("address", address);
        return "saved";
    }
}

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 two templates:

  • index.html - view with the main form that contains telephone number component,
  • saved.html - this view is used to present the submitted telephone number.

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 Input Telephone Number</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/intl-tel-input/css/intlTelInput.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 Telephone Number</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">
            <form method="post" th:object="${address}">
                <div class="form-group">
                    <label for="tel">Telephone</label><br/>
                    <input type="text" class="form-control" id="tel" autocomplete="off"
                           th:field="*{tel}"/>
                </div>

                <button class="btn btn-primary" type="submit">Submit form</button>
            </form>
        </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/intl-tel-input/js/intlTelInput-jquery.js}"></script>

<script>
    $("#tel").intlTelInput();
</script>

</body>
</html>

We used external JavaScript plugin for creating responsive Telephone Inputs: https://github.com/jackocnr/intl-tel-input. It allows us to select country code from a list and automatically choose a flag by provided telephone number.

The saved.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 Input Telephone Number</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 Telephone Number</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-sm-12 mt-5">
            <p>
                <label>Tel: </label><br/>
                <strong th:text="${address.tel}"></strong>
            </p>

            <a th:href="@{/}" class="btn btn-primary">Go back</a>
        </div>
    </div>
</div>

</body>
</html>

5. The output

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

Thymeleaf bootstrap telephone number input

6. Conclusion

In this article, we presented Thymeleaf Telephone Number Input component. The special input is responsive, compatible with the bootstrap framework and allows selecting country flags automatically.

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

{{ message }}

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