Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Passar valores do checkBox para o controller no spring mvc

Estou tentando passar o valor do check box para o ProjetoController mas a view me retorna "typeMismatch: tipo de dado inválido". Alguém consegue me dar uma direção?

Segue as classes:

Projeto

package br.com.csembrasil.compras.models;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;

@SuppressWarnings("serial")
@Entity
public class Projeto implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String projeto;

    @ManyToMany
    private List<CentroDeCusto> centroDeCustos = new ArrayList<>();

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getProjeto() {
        return projeto;
    }

    public void setProjeto(String projeto) {
        this.projeto = projeto;
    }

    public List<CentroDeCusto> getCentroDeCustos() {
        return centroDeCustos;
    }

    public void setCentroDeCustos(List<CentroDeCusto> centroDeCustos) {
        this.centroDeCustos = centroDeCustos;
    }

}

ProjetoDao

package br.com.csembrasil.compras.daos;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import br.com.csembrasil.compras.models.Projeto;

@Repository
@Transactional
public class ProjetoDao {

    @PersistenceContext
    private EntityManager em;

    private DAO<Projeto> dao;

    public void adiciona(Projeto t) {
        dao.adiciona(t);
    }

    public void remove(Projeto t) {
        dao.remove(t);
    }

    public void atualiza(Projeto t) {
        dao.atualiza(t);
    }

    public List<Projeto> listaTodos() {
        return dao.listaTodos();
    }

    public Projeto buscaPorId(Integer id) {
        return dao.buscaPorId(id);
    }

}

Controller

package br.com.csembrasil.compras.controllers;

import java.io.Serializable;
import java.util.List;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import br.com.csembrasil.compras.daos.CentroDeCustoDao;
import br.com.csembrasil.compras.daos.ProjetoDao;
import br.com.csembrasil.compras.models.Projeto;
import br.com.csembrasil.compras.validation.ProjetoValidation;

@Controller
@RequestMapping("/projeto")
public class ProjetoController implements Serializable {

    private static final long serialVersionUID = 1L;

    @Autowired
    private ProjetoDao projetoDao;

    @Autowired
    CentroDeCustoDao centroDeCustoDao;

    @RequestMapping("form")
    public ModelAndView form(Projeto projeto) {

        ModelAndView modelAndView = new ModelAndView("projeto/form");
        modelAndView.addObject("centroDeCustos", centroDeCustoDao.listaTodos());

        return modelAndView;
    }

    @RequestMapping(method = RequestMethod.POST)
    public ModelAndView gravar(@Valid Projeto projeto, BindingResult result,
            RedirectAttributes redirectAttributes) {

        if (result.hasErrors()) {
            return form(projeto);
        }

        if (projeto.getId() == null) {
            projetoDao.adiciona(projeto);            
        } else {
            projetoDao.atualiza(projeto);            
        }

        redirectAttributes.addFlashAttribute("messages",
                "Projeto cadastro com sucesso" );

        return new ModelAndView("redirect:/projeto");
    }
3 respostas
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="s"%>
<%@ taglib uri="http://www.springframework.org/security/tags"
    prefix="security"%>

<%@ taglib tagdir="/WEB-INF/tags" prefix="tags"%>

<tags:pageTemplateForm titulo="Cadastrar Projeto"
    tituloPanelHeading="Adicionar Projeto"
    modelAttribute="projeto"
    actionForm="${s:mvcUrl('PC#gravar').build() }">
    <jsp:body>
        <div class="form-group">
            <label>Insira o nome do Projeto</label>
            <form:input path="projeto" class="form-control" />
            <form:errors path="projeto" class="text-danger" />
        </div>

        <!-- checkbox -->
        <div class="input-group mb-3">
            <c:forEach items="${centroDeCustos }" var="centroDeCusto">
                <div class="input-group-prepend">
                    <div class="input-group-text">
                        <input value="${centroDeCusto.id }" name="centroDeCustos" type="checkbox" aria-label="Checkbox for following text input">
                    </div>
                </div>
                <input value="${centroDeCusto.centroDeCusto }" name="centroDeCustos" type="text" class="form-control" aria-label="Text input with checkbox"
                              id="disabledInput" disabled>
            </c:forEach>
        </div>

        <form:errors path="centroDeCustos" class="text-danger" />
        <br />
        <button type="submit" class="btn btn-success">Cadastrar</button>
    </jsp:body>
</tags:pageTemplateForm>

Consegui passar os centros de custo selecionados para o controller, mas quando um centro de custo não é selecionado ele vai como null na lista e me joga uma exception "TransientObjectException". Se eu seleciono todos os checkbox do centro de custo, o projeto é salvo e o relacionamento também.

Minha JSP ficou assim:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="s"%>
<%@ taglib uri="http://www.springframework.org/security/tags"
    prefix="security"%>

<%@ taglib tagdir="/WEB-INF/tags" prefix="tags"%>

<tags:pageTemplateForm titulo="Cadastrar Projeto"
    tituloPanelHeading="Adicionar Projeto"
    modelAttribute="projeto"
    actionForm="${s:mvcUrl('PC#gravar').build() }">
    <jsp:body>
        <div class="form-group">
            <label>Insira o nome do Projeto</label>
            <form:input path="projeto" class="form-control" />
            <form:errors path="projeto" class="text-danger" />
        </div>

        <!-- checkbox -->
        <div class="form-group">
            <label>
                Centro de custo:
            </label>
            <br />

            <c:forEach items="${centroDeCustoList}" var="centroDeCusto" varStatus="status">
                <c:set var="contains" value="false"/>

                <c:forEach items="${produto.centroDeCustos}" var="centroDeCustoProjeto" varStatus="statusProjeto">
                    <c:if test="${centroDeCustoProjeto.id == centroDeCusto.id}">
                        <c:set var="contains" value="true"/>        
                    </c:if>
                </c:forEach>    
                <c:choose>    
                    <c:when test="${contains}">
                        <form:checkbox path="centroDeCustos[${status.index}].id" value="${centroDeCusto.id}" label="${centroDeCusto.centroDeCusto}" checked="checked" />
                        <c:set var="contains" value="false"/>        
                    </c:when>
                    <c:when test="${not contains }">
                        <form:checkbox path="centroDeCustos[${status.index}].id" value="${centroDeCusto.id}" label="${centroDeCusto.centroDeCusto}" />
                    </c:when>
                </c:choose>
            </c:forEach>
        </div>

        <form:errors path="centroDeCustos" class="text-danger" />
        <br />
        <button type="submit" class="btn btn-success">Cadastrar</button>
    </jsp:body>
</tags:pageTemplateForm>
solução!

Consegui resolver seguindo a solução desse tópico. https://cursos.alura.com.br/forum/topico-binding-em-relacionamentos-many-to-many-41866