Olá, tudo bem? Um dos problemas é que o seu DividasForm espera três parâmetros: dataVencimento, valor e categorias, então no seu form do HTML devem existir campos com esses três nomes especificamente. No seu select, o name está como categorias.id, então não acontece a ligação entre o categorias.id do select do form HTML e o categorias do DividasForm, eles precisam ter o mesmo nome. Uma outra questão complicada é que uma dívida pode ter mais de uma categoria, enquanto o select por padrão só permite escolher uma, mas dá pra mudar isso:
<select id="categorias" name="categorias" th:field="${categorias}" class="form-control" aria-label="Default select example" multiple>
<option th:each="item : ${categorias}" th:value="${item.id}" selected="selected" th:text="${item.categoria}"></option>
</select>
Repare que no fim da linha do select foi colocado a palavra multiple, que passa a permitir que mais de uma opção seja escolhida, para isso é só apertar e segurar a tecla Ctrl do teclado enquanto clicar nas opções, você pode ver mais sobre esse tipo de select no site: https://www.w3schools.com/tags/att_select_multiple.asp. Porém, mesmo com essa alteração provavelmente vai ser preciso mudar a forma como os dados do formulário vão ser recebidos e convertidos para fazer essa parte de várias categorias serem selecionadas ao mesmo tempo funcionar. Lembrando que o valor que será passado pelo select é o id da categoria, e não a categoria em si, como mostra no código abaixo com o th:value recebendo o item.id, então no DividasForm vai ser preciso buscar as categorias por Id no banco de dados para converter corretamente os dados:
<option th:each="item : ${categorias}" th:value="${item.id}" selected="selected" th:text="${item.categoria}"></option>
Também é possível passar direto a categoria inteira como valor na option, assim fica mais fácil de converter os dados, além de que o próprio banco de dados vai inserir na tabela somente o id das categorias na tabela na forma de chave estrangeira (Foreign Key que faz a relação entre tabelas diferentes), e não todas as informações das categorias, então no fim dá no mesmo:
<option th:each="item : ${categorias}" th:value="${item}" selected="selected" th:text="${item.categoria}"></option>
Outras opções além do <select multiple> é usar um <input type="checkbox" /> para cada categoria, ou então usar alguma abordagem diferente usando JavaScript para criar uma lista com o ID das categorias no próprio arquivo HTML e depois enviar ela para o formulário para só então poder fazer a conversão para uma lista em Java. Outra opção seria colocar um número máximo de categorias e então ter um select para cada categoria que a dívida pode ter, por exemplo, se cada dívida pudesse ter no máximo três categorias, daria para ter três selects. Com essa última abordagem seria necessário ter três parâmetros diferentes para cada categoria, como categoria1, categoria2 e categoria3, depois no seu DividasForm você colocaria as três categorias em uma lista.
<select id="categoria1" name="categoria1" th:field="${categorias}" class="form-control" aria-label="Default select example">
<option th:each="item : ${categorias}" th:value="${item}" selected="selected" th:text="${item.categoria}"></option>
</select>
<select id="categoria2" name="categoria2" th:field="${categorias}" class="form-control" aria-label="Default select example">
<option th:each="item : ${categorias}" th:value="${item}" selected="selected" th:text="${item.categoria}"></option>
</select>
<select id="categoria3" name="categoria3" th:field="${categorias}" class="form-control" aria-label="Default select example">
<option th:each="item : ${categorias}" th:value="${item}" selected="selected" th:text="${item.categoria}"></option>
</select>
Então o DividasForm ficaria assim:
private Date dataVencimento;
private BigDecimal valor;
private CategoriaDividas categoria1;
private CategoriaDividas categoria2;
private CategoriaDividas categoria3
public Dividas converter() {
List<CategoriaDividas> categorias = new ArrayList<CategoriaDividas>();
// Fazer validações e depois adicionar na lista
categorias.add(categoria1);
categorias.add(categoria2);
categorias.add(categoria3);
return new Dividas(dataVencimento, valor, categorias);
}
Enfim, é um caso mais complexo e com várias possibilidades, mas espero ter ajudado!