Spring MVC Thymeleaf formularios

Seguimos viendo el motor de plantillas Thymeleaf, en el tutorial anterior aprendimos como integrarlo a una aplicación Spring MVC y vimos algunas características básicas del mismo, en este nuevo tutorial centraremos nuestra atención en el trabajo con formularios, veremos como podemos enlazar los datos del modelo con un formulario, además realizaremos la validación de los datos en el formulario.

Para este ejemplo usaremos el código que desarrollamos en el tutorial, Spring MVC Validación de Formularios JSP, solo que reemplazaremos el motor de vistas JSP por Thymeleaf, todo lo demás quedara exactamente igual, salvo la clase de configuración en la que debemos agregar los beans necesarios y el archivo pom.xml en el que agregaremos las dependencias, esto lo vimos en el tutorial, Spring MVC Configurar Thymeleaf.

Usar Formularios en Thymeleaf

Para trabajar con formularios usaremos th:action="@/url" para indicar la URL a la enviaremos los datos del formulario al presionar el botón Submit. th:object="${atributo}" nos permite establecer a que atributo del modelo estará enlazado el formulario, th:field="*{campo}" nos permite enlazar una propiedad del objeto al que este vinculado el formulario a un elemento de este formulario, por ejemplo, enlazar un campo de texto a la propiedad nombre.

<form th:action="@{/user/create}" th:object="${usuario}" method="post">
    <fieldset>
        <legend>Datos del usuario</legend>
        <table>
            <tr>
                <td><label th:text="#{form.user.nombre}">Nombre: </label></td>
                <td><input type="text" th:field="*{nombre}" /></td>
            </tr>
            <tr>
                <td><label th:text="#{form.user.apellido}">Apellido: </label></td>
                <td><input type="text" th:field="*{apellido}" /></td>
            </tr>
            <tr>
                <td><label th:text="#{form.user.correo}">Correo: </label></td>
                <td><input type="text" th:field="*{correo}" /></td>
            </tr>
            <tr>
                <td><label th:text="#{form.user.pass}">Password: </label></td>
                <td><input type="password" th:field="*{password}" /></td>
            </tr>
            <tr>
                <td><label th:text="#{form.user.edad}">Edad: </label></td>
                <td><input type="number" th:field="*{edad}" /></td>
            </tr>
            <tr>
                <td><label th:text="#{form.user.sexo}">Sexo: </label></td>
                <td><input type="checkbox" th:field="*{sexo}" /></td>
            </tr>
            <tr>
                <td>
                    <button type="submit">Registrar...</button>
                </td>
            </tr>
        </table>
    </fieldset>
</form>

La etiqueta <label th:text="#{form.user}"/> nos permite mostrar un mensaje de texto extraído de un archivo de propiedades i18n, como lo vimos en el tutorial anterior.

src/main/resources/messages_es.properties

form.user.nombre=Nombre del usuario
form.user.apellido=Apellido materno y paterno
form.user.correo=Correo electronico
form.user.edad=Edad del usuario
form.user.sexo=Eres hombre o mujer
form.user.pass=Tu contraseña

Nuestro controlador para manejar este formulario ya lo hemos explicado en tutoriales previos, solo mostraremos el código:

@Controller
@RequestMapping("/user")
public class UsuarioController {
    
    @RequestMapping("/form")
    public String showUserForm(Model model){
        model.addAttribute("usuario", new Usuario());
        return "userForm";
    }

    @RequestMapping("/create")
    public ModelAndView createUser(@Valid Usuario user, BindingResult result) {
        ModelAndView model = new ModelAndView();
        model.addObject("usuario", user);
        model.setViewName(result.hasErrors() ? "userForm" : "userReady"); 
        return model;
    }
}

Al correr nuestra aplicaciones veremos:

image

Con esto tenemos nuestro formulario listo, si introducimos los datos correctamente y presionamos el botón Registrar… veremos el correspondiente mensaje de éxito.

Validar Formularios con Thymeleaf

Lo siguiente que haremos será asegurarnos de que los datos introducidos por el usuario sean correctos, si no es así mostraremos los mensajes correspondientes.

El tema de validación de datos ya lo vimos en el tutorial validar formularios, recordemos que utilizaremos Hibernate Validator y anotaremos nuestra clase Usuario con las correspondientes anotaciones.

Requerimos la siguiente dependencia:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.3.4.Final</version>
</dependency>

La clase Usuario anotada:

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotBlank;

public class Usuario {

    @Size(min = 3, max = 20, message = "el nombre debe tener mas de 3 letras y menos de 20.")
    private String nombre;

    @NotBlank(message = "debe indicar el apellido del usuario.")
    private String apellido;

    @Email
    @NotBlank
    private String correo;

    @Pattern(regexp = "^[a-zA-Z]\\w{3,14}$", message = "debe contener letras seguidos de numeros")
    private String password;

    @Min(value = 18, message = "el usuario debe tener 18+")
    @NotNull
    private Integer edad;

    @NotNull
    private Boolean sexo;

   // getter y setter ...

}

Para mostrar los errores de validación en la vista hacemos lo siguiente:

<form th:action="@{/user/create}" th:object="${usuario}" method="post">

    <div class="errorblock" th:if="${#fields.hasErrors('*')}">
        <ul>
            <li th:each="err : ${#fields.errors('*')}"
                th:text="${err}">Input is incorrect</li>
        </ul>
    </div>

    <!-- mas... -->

</form>

Este código crea un elemento div que contiene todos lo errores encontrados en el formulario, usaremos th:if="${#fields.hasErrors('*')}" para determinar si se ha encontrado algún error, de ser así se crea el div, th:each="err : ${#fields.errors('*')}" nos permite recorrer cada uno de los errores.

image

Si deseamos mostrar los mensajes de error individualmente, por ejemplo, mostrar el error al lado del campo correspondiente, usando th:errors="*{nombre}" obtenemos el mensaje de error producido al introducir un nombre incorrecto, th:if="${#fields.hasErrors('nombre')}" con esto comprobamos si hubo un error en el campo nombre.

<tr>
    <td><label th:text="#{form.user.nombre}">Nombre: </label></td>
    <td><input type="text" th:field="*{nombre}" /></td>
    <td th:if="${#fields.hasErrors('nombre')}">
        <span th:errors="*{nombre}" />
    </td>
</tr>

En este ejemplo el mensaje de error se muestra en un elemento span al lado del campo nombre.

Una forma de simplificar el manejo de errores en los formularios es usar th:errorclass="..." de este modo aplicamos una clase CSS al elemento que tenga un error.

<tr>
    <td><label th:text="#{form.user.nombre}">Nombre: </label></td>
    <td><input type="text" th:field="*{nombre}" th:errorclass="errorfield"/></td>
</tr>

image

Con esto terminamos el tutorial, más adelante seguiremos viendo otras características de este motor de plantillas.

Comentarios

Temas relacionados

Entradas populares de este blog

tkinter Grid

Controles y Contenedores JavaFX 8 - I

tkinter Canvas

Histogramas OpenCV Python