Crear Usuario y Validacion de campos
Necesitaremos un método en el controlador que reciba el formulario, lo valide, guarde el usuario y retorne una respuesta a la vista.
Este metodo recibira mas que Model como parametro, necesitara un objeto User que tendra mapeado todos los campos del formulario y un objecto con el resultado de la validacion del formulario.
Contenido
- Agregar Validacion a la entidad Usuario.
- Agregar
de error al HTML.mensajes - Crear
metodo en elcontrolador . - Crear Servicio para
guardar usuario . - Arreglar Formulario HTML.
- Git Commit.
- Video Paso a Paso.
1.Agregar Validacion
Para usar el BindingResult cuando tratamos de crear un usuario, necesitaremos anotar los campos que queramos validar. Hay una gran lista de anotacions que se pueden usar, puedes encontrar mas informacion en este link (click aqui).
Utilizaremos solo dos (@NotBlank, @Email) en nuestro ejemplo pero puedes probar los que quieras.
*@NotBlank: El valor no puede ser null y debe contener al menos un caracter que no sea espacio.
*@Email: Valida que el valor ingresado tenga el formato valido de email.
@Column
@NotBlank
private String firstName;
@Column
@NotBlank
private String lastName;
@Column(unique = true)
@Email
@NotBlank
private String email;
@Column(unique = true)
@NotBlank
private String username;
@Column
@NotBlank
private String password;
2.Agregar mensajes de error
Inmediatamente debajo de cada campo de texto deberas colocar la siguiente linea de codigo, que solo aparecera si hay un error para ese campo.
<div class="alert-danger" th:if="${#fields.hasErrors('Nombre_del_atributo')}" th:errors="*{Nombre_del_atributo}">Name Error</div>
Como resultado todos tus campos se deberian de ver de la siguiente manera
<div class="form-group row">
<label class="col-lg-3 col-form-label form-control-label">First name</label>
<div class="col-lg-9">
<input class="form-control" type="text" th:field="${userForm.firstName}" th:disabled="${disableFields}">
<div class="alert-danger" th:if="${#fields.hasErrors('firstName')}" th:errors="*{firstName}">Name Error</div>
</div>
</div>
3.Crear metodo en el Controlador.
Para este metodo necesitaremos agregar mas que el modelo a la firma como lo hicimos en el metodo anterior, esta vez recibiremos 2 parametros mas, uno que es el usuario mapeado desde el formulario y el otro sera el resultado de ese mapeo.
- @PostMapping: Indica que para acceder a este metodo debe ser utilizando un llamado POST y no GET, ademas que la ruta debe de ser /userForm
- @Valid: Indica Spring que verifique los atributos del entity, en este caso @NotBlank y @Email.
- @ModelAttribute: El constructor de esta anotacion recibe el nombre del formulario html y lo convierte a un objeto Java.
- BindingResult: Contendra la informacion del resultado entre el mapeo del formulario html y el objeto Java User.
Lo primero que debemos hacer es verificar que no hayan errores dentro de nuestro BindingResult de la siguiente manera: result.hasErrors().
Si hay errores necesitaremos regresar a la pantalla para poder mostrar estos errores, esto lo hicimos en el punto #2 poniendo una seccion de errores debajo de cada input, y ademas debes indicar que la pestaña del formulario debe de estar activa y sino hay errores hay que proceder a crear el usuario.
El codigo final del metodo descrito seria el siguiente dentro de la clase UserController:
4. Crear Servicio
Tendras que agregar el metodo a la interfaz del servicio y luego crear el metodo en la implementacion. Pero antes de crear el usuario tenemos que hacer dos validaciones, que el username no este ocupado por otra persona y que el password y el confirmPassword sean iguales.
UserServicepublic User createUser(User formUser) throws Exception;
UserServiceImpl
private boolean checkUsernameAvailable(User user) throws Exception {
Optional<User> userFound = repository.findByUsername(user.getUsername());
if (userFound.isPresent()) {
throw new Exception("Username no disponible");
}
return true;
}
private boolean checkPasswordValid(User user) throws Exception {
if ( !user.getPassword().equals(user.getConfirmPassword())) {
throw new Exception("Password y Confirm Password no son iguales");
}
return true;
}
@Override
public User createUser(User user) throws Exception {
if (checkUsernameAvailable(user) && checkPasswordValid(user)) {
user = repository.save(user);
}
return user;
}
Nota:Cuando agregemos Spring Boot Security necesitaremos encriptar el password antes de guardar el usuario.
5.Arreglar Formulario HTML
Para poder que el formulario haga el request apropiadamente asegurate que este usando el metodo post, el action sea userForm y el boton de guardar los cambios sea tipo submit.
<form id="userForm" th:object="${userForm}" method="post" class="form" role="form" th:action="@{/userForm}">
Ademas asegurate de haber programado el cambio de pestañas adecuadamente en el archivo form-view.html. Tanto los enlaces de cada tab como el cuerpo deben de tener el atributo th:classappend.
6.Git Commit
Se me olvido tomar la captura de pantalla antes de hacer el commit por lo tanto esta imagen es diferente a las anteriores. Esta imagen muestra la informacion del commit, como el commit Id, el mensaje y los archivos modificados en ese commit.
7.Video Paso a Paso
Menu
- Setup
- Entidades y POJOS
- Basic HTML
- Lista de Usuarios
- Crear Usuario y Validar Campos
- Editar Usuario
- Eliminar Usuario
- Cambiar Contraseña
- Spring Security
- Paginas de Error
- Bonus, Arreglando Cositas
- Formulario de registro
- Despliegue en Heroku
Gracias por llegar al final de este post.
No se te olvide dejar tus comentario o preguntas aca abajo o en mi twitter @Cruizg93
En el minuto 2:35 agregamos los mensajes de errores, pero tengo una duda si tengo una relacion de oneToOne, como lo haces en tu tutorial Spring Boot -06- JPA Relaciones de uno a uno y de muchos a muchos (LINK: https://www.youtube.com/watch?v=0Iaafne6BRs&t=1287s) en este caso como pondria el div que contiene el error en mi caso tengo una relacion de 1 a 1 de cliente con usario y accedo al campo de esta forma th:field=”${clienteForm.users.nombres}” pero en el div especificaria igual como lo haces aqui th:if=”${#fields.hasErrors(‘Nombre_del_atributo’)}” th:errors=”*{Nombre_del_atributo} o tendria que poner th:if=”${#fields.hasErrors(‘users.Nombre_del_atributo’)}” gracias por responder de antemano.
Hola Cristian,
Debo molestarte… estoy realizando lo que me comentas para validar tanto contraseñas como campos… entiendo que lo hice de acuerdo a como tu nos estas enseñando, pero lo cierto es que no me aparece ningun tipo de validación salvo las de campo vacío, ¿alguna sugerencia?
Lo primero q se viene a mi mente es que tienes q revisar los import, todas las validaciones pertenecen al paquete javax.validation.constraints. Por lo tanto si pones un * deberias de poder usar todas.
Si compartes el codigo completo de tu entidad/pojo yo podria revisar que tienes mal.
Tenías tooodaaa la razón… solo estaba el import javax.validation.Valid;…. lo cambié a import javax.validation.*; y ahora todo anda de maravillas
Donde encuentro los codigos fuentes de estos videotutorilaes de spring tool?
https://github.com/cruizg93/Spring-Boot-Aplicacion