Atualizando um produto

Até agora fizemos uma aplicação que exibe uma lista de produtos e mostra os detalhes de cada um deles. Agora vamos adicionar a funcionalidade de atualizar um produto.

Para isso, vamos adicionar um link na página de detalhes de um produto que leva para uma página de formulário para atualizar o produto. Essa página vai ter um formulário com os dados do produto e um botão para enviar o formulário.

Nessa etapa vamos juntar os conhecimentos aprendidos anteriormente para conseguir fazer essa funcionalidade. Vamos começar criando uma nova rota para a página de formulário de atualização de produto usando a visão list que vai ser bem similar a que usamos para detalhar o produto, mudando apenas o nome da página.

1
<td>
2
<a th:href="@{/products/show(id = ${product.id})}">Show</a>
3
<a th:href="@{/products/edit(id = ${product.id})}">Edit</a>
4
</td>

Agora precisamos criar a rota para essa página que deve receber o parâmetro id que vai ser o id do produto que queremos atualizar. Vamos criar um novo método no nosso controller para essa rota.

1
@GetMapping("/products/edit")
2
public String edit(Model model, @RequestParam("id") String id){
3
Product product = findProductById(id);
4
model.addAttribute("product", product);
5
return "edit";
6
}

Perceba que o método é bem similar ao método show que criamos anteriormente, com a mesma lógica de recupear o id passado via URL, fazer a busca do produto na lista de produtos, adicionar esse produto no container da visão e retornar o nome da visão, que nesse caso chamamos de edit pois é uma nova página.

Vamos criar essa nova página edit.html na pasta src/main/resources/templates. A ideia é que essa página seja bem similar a página create que criamos anteriormente, com um formulário para atualizar o produto, só que dessa vez um formulário populado com os dados daquele produto em questão.

1
<form method="post" th:action="@{/products/update}">
2
3
<input type="hidden" th:field="${product.id}" id="id">
4
5
<label for="name">Nome</label>
6
<input type="text" th:field="${product.name}" id="name">
7
8
<label for="description">Descrição</label>
9
<input type="text" th:field="${product.description}" id="description">
10
11
<label for="price">Preço</label>
12
<input type="text" th:field="${product.price}" id="price">
13
14
<button type="submit">Salvar</button>
15
</form>

Temos 2 modificações importantes nesse formulário em comparação ao formulário de novo produto. A primeira é que adicionamos um campo hidden para o id do produto. Esse campo é necessário para que o Spring consiga identificar qual produto estamos atualizando. A segunda modificação é a rota, que em vez de apontar para store agora aponta para update. Ou seja, em vez de apenas cadastrar esse novo produto, vamos atualizar um produto já existente.

A última parte do nosso trabalho é criar a rota para atualizar o produto. Vamos criar um novo método no nosso controller para essa rota.

1
@PostMapping("/products/update")
2
public String update(Product product){
3
Product productToUpdate = findProductById(product.getId());
4
productToUpdate.setName(product.getName());
5
productToUpdate.setDescription(product.getDescription());
6
productToUpdate.setPrice(product.getPrice());
7
return "redirect:/products";
8
}

Nessa rota temos mapeado o método Post pois os dados estão vindo diretamente do formulário e não via URL. Além disso, temos um parâmetro Product que é o produto que estamos atualizando. Esse parâmetro é preenchido automaticamente pelo Spring com os dados do formulário, pois os campos do formulário tem o mesmo nome dos atributos da classe Product.

A partir desses dados, fazemos a busca do produto na lista de produtos e atualizamos os dados desse produto com os dados que vieram do formulário. Por fim, retornamos um redirecionamento para a página de listagem de produtos. Teste no navegador e verá que agora é possível atualizar um produto.