O elemento select
é bastante utilizado em sistemas pois permite que o usuário selecione uma opção entre uma lista de opções. Você já deve estar familiarizado com esse elemento, de uma olhada na estrutura básica de um select
:
1<select name="estado">2 <option value="">Estado</option>3 <option value="SP">São Paulo</option>4 <option value="SC">Santa Catarina</option>5 <option value="PR">Paraná</option>6</select>
O elemento é formado por uma tag select
que indica o ínicio e o fim do elemento e uma lista de tags option
que representam as opções que o usuário pode selecionar. Cada tag option
possui um atributo value
que indica o valor que será enviado para o servidor quando o usuário selecionar a opção. O texto que aparece dentro da tag option
é o texto que será exibido para o usuário.
Porém, como você pode perceber, a lista de opções é estática, ou seja, ela não é gerada dinamicamente, caso queira alterar a lista é preciso alterar o código HTML. Para que a lista seja gerada dinamicamente é preciso que os dados da lista venham do servidor.
Primeiramente vamos criar uma classe que representará a lista de opções as quais o usuário poderá selecionar:
1public class Categories {2 public static final String[] CATEGORIES = new String[] {"Desktop", "Notebook", "Smartphone"};3}
Essa classe possui um atributo estático que é um array de String
que contém as opções que o usuário poderá selecionar.
Existem maneiras mais elegantes de fazer isso, porém, para manter o foco no Spring Boot, vamos manter dessa forma.
Agora precisamos adicionar ao nosso formulário o elemento select
que irá exibir as opções para o usuário. Para isso, na página product-form.html
adicione o seguinte código dentro do formulário:
1 <label for="category">Categoria</label>2 <select name="category" id="category">3 <option value="">Selecione uma categoria</option>4 <option value="Desktop">Desktop</option>5 <option value="Notebook">Notebook</option>6 <option value="Smartphone">Smartphone</option>7 </select>
So você rodar a aplicação irá perceber que o elemento select
já está sendo exibido, porém a lista de opções continua estática e não dinâmica. Para tornar a lista dinâmica é preciso que a visão tenha acesso aos dados da classe Categories
. Para isso, altere o método create`` da classe
ProductController` para que ele envie a lista de categorias para a visão:
1 @GetMapping("/products/create")2 public String create(Model model) {3 Product product = new Product();4 model.addAttribute("product", product);5 model.addAttribute("categories", Categories.CATEGORIES);6 return "product/create";7 }
Agora precisamos alterar a visão para que ela utilize a lista de categorias que foi enviada pelo controlador. Para isso, altere o elemento select
para que ele utilize a lista de categorias:
1 <label for="category">Categoria</label>2 <select name="category" id="category">3 <option value="">Selecione uma categoria</option>4 <option th:each="category : ${categories}" th:value="${category}" th:text="${category}"></option>5 </select>
Rode a aplicação e você verá que a lista de opções está sendo gerada dinamicamente. Para confirmar isso, adicione uma nova categoria na classe Categories
e rode a aplicação novamente, você verá que a nova categoria aparece automaticamente na lista de opções.
Analisando o código acima, você pode perceber que o elemento option
possui um atributo th:each
que indica que o elemento option
será repetido para cada elemento da lista ${categories}
. Dentro do elemento option
ainda existem dois atributos th:value
e th:text
que indicam respectivamente o valor que será enviado - atributo value
do elemento - para o servidor e o texto que será exibido para o usuário.
Você pode conferir o HTML final que está sendo gerado utilizando a opção de verificar o código fonte da página no navegador. Faça isso clicando com o botão direito do mouse na página e selecionando a opção Ver código fonte da página
ou pelo atalho do teclado Ctrl + U
. O código será similar ao seguinte:
1 <label for="category">Categoria</label>2 <select name="category" id="category">3 <option value="">Selecione uma categoria</option>4 <option value="Desktop">Desktop</option>5 <option value="Notebook">Notebook</option>6 <option value="Smartphone">Smartphone</option>7 </select>
Veja que o HTML gerado é exatamente o mesmo que foi escrito no começo do artigo, com os valores do atributo value
e o texto que será exibido para o usuário sendo gerados dinamicamente.
Sempre que você estiver com dúvidas sobre o HTML gerado, utilize a opção de verificar o código fonte da página no navegador. Isso irá te ajudar a entender o que está acontecendo.
Se você tentar fazer a submissão do formulário verá que o produto continua sendo salvo normalmente, porém, o atributo category
não está sendo utilizado para nada. Isso acontece porque o atributo category
ainda não existe na classe Product
e nem no banco de dados. Para resolver isso, será preciso adicionar o atributo category
na classe Product
. Termine o código adicionando o atributo category
na classe Product
e alterando os demais locais afetados por essa mudança.
Outra parte importante é na página de atualização do formulário. Nessa página os dados do produto já vem previamente populados no formulário e se você observar o campo de categoria sempre está vindo a primeira opção e não a categoria cadastrada no produto.
Isso acontece porque para que uma das opções esteja selecionada por padrão é necessário informar qual das tags option
deve ser selecionada. Para isso se utiliza o atributo selected
do HTML. Para facilitar o desenvolvimento o Thymeleaf fornece o dialeto th:selected
.
Agora para saber qual das options deve ser selecionada, basta fazer uma comparação entre o que está no campo product.category
do objeto Product
com a lista de categorias em category
. Veja como irá ficar o código final:
1<label for="category">Categoria</label>2<select name="category" id="category">3 <option value="">Selecione uma categoria</option>4 <option th:each="category : ${categories}"5 th:value="${category}"6 th:text="${category}"7 th:selected="${product.category == category}">8 </option>9</select>