I have a form with two dropdowns, One for selecting a group and the other one for selecting a material so the commandName is DTO class which contains two List fields of "Group" and "Material" classes, i have another class "Absence" mapped ManyToOne to class Student and class Material too, i want to list the students of the selected group to mark their absence in the selected material,also class Absence has a String field which has "present" or "absent" as value and a Date field,how to do that?
Any help on this would be appreciated, Thank you
here is DTO class
public class ListeleveDTO {
private java.util.List<Groupe> groupe;
private java.util.List<Matiere> matiere;
public ListeleveDTO() {
}
public ListeleveDTO(java.util.List<Groupe> groupe, java.util.List<Matiere> matiere) {
this.groupe= groupe;
this.matiere = matiere;
}
Class Absence
#Entity
#Table(name = "Absence")
public class Absence implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
#Column(name="Date", nullable=false)
private Date date;
#Column(name="Etat", unique=true,nullable=false)
private EtatAbs etat;//enum class which contains "Present" or "Absent"
#ManyToOne
#JoinColumn(name="Eleve_id", referencedColumnName="id")
private Eleve eleve;
#ManyToOne
#JoinColumn(name="Matiere_id", referencedColumnName="id")
private Matiere matiere;
//getters and setters
jsp form
<form:form method="post" commandName="listeleveDTO" role="form" >
<label>Sélectionnez un groupe</label>
<select name="Groupe" class="form-control">
<option value="NONE" label="--- Select ---" />
<c:forEach items="${listeleveDTO.groupe}" var="m">
<option value="${m.libelle}">${m.libelle} </option>
</c:forEach>
</select>
<div class="form-group" style="margin-top:50px">
<label> Sélectionnez une matiere</label>
<select name="Matiere" class="form-control">
<option value="NONE" label="--- Select ---" />
<c:forEach items="${listeleveDTO.matiere}" var="mg">
<option value="${mg.libelle}">${mg.libelle} </option>
</c:forEach>
</select>
</div>
<button type="submit" class="btn btn-info" style="margin-top:30px" >Valider</button>
</form:form>
Controller
#Controller
#RequestMapping ("abs")
#SessionAttributes({"groupe","matiere"})
public class AbsController {
#Autowired GroupeService groupeservice;
#Autowired AbsenceService absenceService;
#Autowired MatiereService matiereservice;
#RequestMapping(method = RequestMethod.GET)
public ModelAndView showForm() {
ModelAndView mv = new ModelAndView("abs");
ListeleveDTO listeleveDTO = new ListeleveDTO(groupeservice.findAllGroupes(), matiereservice.findAlmatieres());
mv.addObject("listeleveDTO",listeleveDTO );
return mv;
}
#RequestMapping( method = RequestMethod.POST)
public String submitForm( #ModelAttribute("listeleveDTO") ListeleveDTO listeleveDTO,BindingResult result,
ModelMap map
) {
return "listeleve" ;
}
#RequestMapping(value="/listeleve")
public String geteleves (Model model){
model.addAttribute("absence", new Absence());
model.addAttribute("listAbsence", absenceService.findAllAbsence());
model.addAttribute("etats",EtatAbs.values());
return "listeleve";
}
ListofStudent jsp
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th width="200px">Eleve</th>
<th width="150px">Absence</th>
<th width="150px">Edit</th>
</tr>
</thead>
<tbody>
<sql:query dataSource="${ds}" var="result">
SELECT X.FIRST_NAME,X.LAST_NAME,A.Etat,X.id from Absence A, MATIERE M,
(SELECT E.id,E.FIRST_NAME,E.LAST_NAME from GROUPE G, ELEVE E where G.LIBELLE= "<%=liste %>" and E.groupe_id = G.id) as X
where X.id = A.ELEVE_ID and A.MATIERE_ID = M.id and M.LIBELLE = "<%=liste1%>" ;
</sql:query>
//i joined table groupe and eleve(student) to select first and last name of students then i joined table absence to table matiere (material) and table X the result of joining student and group to select field "etat",this field contains "absent" or "present" student
<c:forEach var="row" items="${result.rows}">
<tr class="gradeU">
<td><c:out value="${row.FIRST_NAME}"/> <c:out value="${row.LAST_NAME}"/></td>
<td>
<c:out value="${row.Etat}"/>
</td>
<td></td>
</tr>
</c:forEach>
</tbody>
</table>
Related
this is my html:
when I am seeing the preview in intelliJ of the same page, it is showing the right page but as soon as I run my program the and click on addInvoice button it is just showing the fields which are above the table only ....the table inputs are not showing in browser.The problem is inside<tr th:each product...>
<input type="hidden" th:field="*{primaryKey}"
placeholder="primaryKey" class="form-control mb-4 col-4">
<input type="text" th:field="*{invoiceNo}"
placeholder="invoiceNo" class="form-control mb-4 col-4">
....
....
<table border="1" class="table table-striped table-responsive-md">
<thead>
<tr>
<th>SNo</th>
<th>Product</th>
<th>Description</th>
<th>Price</th>
<th>Qty</th>
<th>Tax%</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr th:each="product,listOfProductsStat:*{listOfProducts}">
<td th:text="${listOfProductsStat.count}">1</td>
<td>
<input type="text" th:field="*{listOfProducts[__${listOfProductsStat.index}__].productName}">
</td>
<td>
<textarea class="form-control rounded-0" name="description" id="description" rows="3"
maxlength="500"
placeholder="Description"
th:field="*{listOfProducts[__${listOfProductsStat.index}__].description}"></textarea>
</td>
<td>
<input type="number" name="price" id="price" class="form-control"
th:field="*{listOfProducts[__${listOfProductsStat.index}__].price}" placeholder="Price">
</td>
<td>
<input type="number" name="qty" class="form-control" id="qty" placeholder="Qty"
th:field="*{listOfProducts[__${listOfProductsStat.index}__].qty}">
</td>
<td>
<input type="number" name="taxPercent" class="form-control" id="taxPercent" placeholder="Tax(%)"
th:field="*{listOfProducts[__${listOfProductsStat.index}__].taxPercent}">
</td>
<td>
<input type="number" name="total" class="form-control" id="total" placeholder="Total"
th:field="*{listOfProducts[__${listOfProductsStat.index}__].total}">
</tr>
</tbody>
</table>
this is my entities:
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
public class InvoiceInfo {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long primaryKey;
// private int SNo;
private String invoiceNo;
private String billTo;
private String status;
#DateTimeFormat(pattern = "yyyy-MM-dd")
private Date invoiceDate;
#DateTimeFormat(pattern = "yyyy-MM-dd")
private Date dueDate;
private double grandTotal;
#OneToMany(mappedBy = "invoiceInfo",cascade = CascadeType.ALL)
private List<Product> listOfProducts=new ArrayList<>();
}
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long productId;
private String productName;
private String description;
private double price;
private int qty;
private int taxPercent;
private double total;
// private double subTotal;
// private int totalTax;
// private String invoiceNote;
#ManyToOne
#JoinColumn(name = "invoice_info_primary_key")
private InvoiceInfo invoiceInfo;
this is my controller:
#Controller
public class InvoiceInfoController {
#Autowired
private InvoiceInfoService invoiceInfoService;
#GetMapping("")
public String InvoiceInfoListPage(Model model) {
model.addAttribute("InvoiceInfoList", invoiceInfoService.getAllInvoiceInfo());
model.addAttribute("products",invoiceInfoService.getAllProducts());
return "Home";
}
#GetMapping("/openNewInvoiceInfoForm")
public String openNewInvoiceInfoForm(Model model) {
InvoiceInfo invoiceInfo = new InvoiceInfo();
model.addAttribute("invoiceInfo", invoiceInfo);
return "new_invoiceInfo";
}
#PostMapping("saveInvoice")
public String saveInvoiceInfo(#ModelAttribute("invoiceInfo") InvoiceInfo invoiceInfo) {
invoiceInfoService.saveInvoiceInfo(invoiceInfo);
return "redirect:/";
}
#GetMapping("/editInvoiceForm/{primaryKey}")
public String editInvoiceForm(#PathVariable(value = "primaryKey") long primaryKey , Model model) {
InvoiceInfo invoiceInfo= invoiceInfoService.getInvoiceByPrimaryKey(primaryKey);
model.addAttribute("invoiceInfo",invoiceInfo);
return "update_invoiceInfo";
}
#GetMapping("/deleteInvoiceByPrimaryKey/{primaryKey}")
public String deleteInvoiceByPrimaryKey(#PathVariable(value = "primaryKey") long primaryKey){
this.invoiceInfoService.deleteInvoiceByPrimaryKey(primaryKey);
return "redirect:/";
}
}
the problem:
<tr th:each="product,listOfProductsStat:*{listOfProducts}">
my code is not even showing the <td>enter image description here tags in browser ..
How should I associate the listOfProducts instance in InvoiceInfo class with the form inputs and save it in Product table one by one?
Please help!
I have the entities book and author, and there is a many-to-many relationship between them (one book can have many authors, one author can have many books). The book class has a private List <Author> authors; field. I pass the list of all authors to the view as model attribute. The view returns an object of the BbookViewModel, whose field is a list of selected author ids. How can I add this id to the list when choosing an option from a select (using thymeleaf)?
BookController
#Controller
public class BookController {
#Autowired
private BookRepository repository;
#Autowired
private AuthorRepository authorRepository;
#GetMapping("/books")
private String getAllBooks(Model model)
{
// some code ...
model.addAttribute("bookModel", new models.Book());
model.addAttribute("allAuthors", authorRepository.findAll());
return "books.html";
}
#PostMapping(value = "/books/create", produces = {MediaType.APPLICATION_JSON_VALUE})
#ResponseBody
public ValidationResponse create(#Valid #ModelAttribute models.Book book, BindingResult result)
{
// ...
}
}
Part of books.html
<form id="bookCreationForm" th:action="#{/books/create}" th:object="${bookModel}"
method="post">
<table class="table">
<tr>
<td><label th:text="Name" /></td>
<td><input type="text" th:field="*{name}" /></td>
</tr>
<tr>
<td><label th:text="Author" /></td>
<td>
<select class="form-control" /*th:field="${}"*/>
<option value="0">Select author</option>
<option th:each="author : ${allAuthors}" th:value="${author.id}" th:text="${author}"></option>
</select>
</td>
</tr>
</table>
</form>
Should I use a multi-select and send the list of ids separately from the book model?
The solution is simple: I just had to add a multiple attribute to the select tag. The binding system will find the authors field in the class Book and link the List to the selected values.
<form id="bookCreationForm" th:action="#{/books/create}" th:object="${bookModel}"
method="post">
<table class="table">
<!-- some book fields-->
<tr>
<td><label th:text="Authors" /></td>
<td>
<select class="form-control" name="authors" multiple>
<option th:each="author : ${allAuthors}" th:value="${author.id}" th:text="${author}"></option>
</select>
</td>
</tr>
</table>
</form>
I have this hibernate model:
#Entity
#Table(name="BlogPost")
public class BlogPost implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column
private String title;
#Column
private String text;
#Column(name="creation_date")
private Date creationDate;
#ManyToOne
#JoinColumn(name = "cat_id")
private PostCategory category;
}
and this form:
<form:form action="saveBlogPost" method="post" modelAttribute="blogPost">
<table>
<form:hidden path="id"/>
<tr>
<td>Title:</td>
<td><form:input path="title" /></td>
</tr>
<tr>
<td>Text:</td>
<td><form:input path="text" /></td>
</tr>
<tr>
<td>Category:</td>
<td>
<form:select path="category">
<c:forEach items="${allCats}" var="cat" >
<form:option value="${cat.id}">
${cat.title}
</form:option>
</c:forEach>
</form:select>
</td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="Save"></td>
</tr>
</table>
</form:form>
and this controller method:
#RequestMapping(value = "/saveBlogPost", method = RequestMethod.POST)
public ModelAndView saveEmployee(#ModelAttribute BlogPost blogPost) {
if (blogPost.getId() == 0) {
blogPost.setCategory(postCategoryServiceImpl.getPostCategory(blogPost.getCategory().getId()));
blogPost.setCreationDate(new Date());
blogPostServiceImpl.addBlogPost(blogPost);
} else {
blogPostServiceImpl.updateBlogPost(blogPost);
}
return new ModelAndView("redirect:/");
}
I set my creationDate in the controller and other fields done by Spring form.
I suspect not setting creationDate in the form caused getting bad request error on form submit.
What should I do to avoid this error?
Looks like same issue as Spring MVC Error: Failed to convert property value of type java.lang.String to required type.
That is, <form:select> only submits a single string value, which you're telling Spring to put into a PostCategory object.
Try telling it to put the value into the category sub-object's id field:
<form:select path="category.id">
I would like to save the inputs to the Set interface. I have class Client.java:
#Table(name = "client")
public class Client {
#OneToOne(cascade = CascadeType.ALL)
private ShippingAddress shippingAddress;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<Address> shippingAddresses = new HashSet<>();
}
Class ShippingAddress.java:
#Table(name = "address")
public class ShippingAddress {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
Long id;
String street;
String zip;
}
And it's my create form:
<form th:action="#{/add}" method="post" th:object="${client}">
<tr>
<td><input class="form-control" type="text" th:field="*{shippingAddress.street}"/></td>
<td><input class="form-control" type="text" th:field="*{shippingAddress.zip}"/></td>
</tr>
It works fine, but I can only save one street and one zip. I tried to improve it in this way to be able to save more data:
<form th:action="#{/add}" method="post" th:object="${client}">
<tr>
<td><input class="form-control" type="text" th:field="*{shippingAddress[0].street}"/></td>
<td><input class="form-control" type="text" th:field="*{shippingAddress[0].zip}"/></td>
</tr>
<tr>
<td><input class="form-control" type="text" th:field="*{shippingAddress[1].street}"/></td>
<td><input class="form-control" type="text" th:field="*{shippingAddress[1].zip}"/></td>
</tr>
But I get information:
Invalid property 'shippingAddress[0]' of bean class [model.Client]: Property referenced in indexed property path 'shippingAddress[0]' is neither an array nor a List nor a Set nor a Map; returned value was [ShippingAddress(id=null, street=null, zip=null, state=null, city=null, country=null)]
To add values to Set I should use the add method? But how to implement it with Thymeleaf?
Method in Controller (save data):
#Transactional
#RequestMapping(value = "add", method = RequestMethod.POST)
public String saveClient(#ModelAttribute Client client) {
clientRepository.save(client);
return "redirect:/";
}
Method in Controller (open create form)
#RequestMapping("/create")
public String newClient(Model model) {
model.addAttribute("client", new Client());
return "create";
}
I want to create a bank account register related to a specific Person in a OneToMany relationship.
I have the clas Pessoa (Person):
#Entity
public class Pessoa {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private int idPessoa;
private String nome;
#OneToMany(mappedBy = "pessoa", targetEntity = ContaCorretora.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<ContaCorretora> contaCorretora;
...and the class ContaCorretora (Bank account):
#Entity
public class ContaCorretora {
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private int idConta;
private TipoConta tipoConta;
private TipoRisco tipoRisco;
private String login;
private String senha;
private BigDecimal valorAtual;
#ManyToOne
#JoinColumn(name="idPessoa")
private Pessoa pessoa;
I'm using this method in Controller for start the process of registration:
#RequestMapping(value = "pessoacorretora/{id}")
public ModelAndView pessoaCorretora(#PathVariable("id") int id, ContaCorretora contaCorretora ) {
Map<String, Object> model = new HashMap<String, Object>();
Pessoa pessoa = pessoaDao.find(id);
model.put("pessoa", pessoa);
model.put("tipoConta", TipoConta.values());
model.put("tipoRisco", TipoRisco.values());
return new ModelAndView("corretora/contacorretora", "model", model);
}
Sumarizining, I have a specific page for recording bank accounts. So, I created this form:
<form:form action="${s:mvcUrl('CC#gravar').build() }" method="post" commandName="contaCorretora" enctype="multipart/form-data" >
<div class="form-group" >
<label>Conta</label>
<select name="tipoConta">
<c:forEach items="${model.tipoConta}" var="tipoConta">
<option value=${tipoConta}>${tipoConta}</option>
</c:forEach>
</select>
</div>
<div class="form-group" >
<label>Risco</label>
<select name="tipoRisco">
<c:forEach items="${model.tipoRisco}" var="tipoRisco">
<option value=${tipoRisco}>${tipoRisco}</option>
</c:forEach>
</select>
</div>
<div class="form-group">
<label>Login</label>
<form:input path="login" cssClass="form-control" />
</div>
<div class="form-group">
<label>Senha</label>
<form:input path="senha" cssClass="form-control" />
</div>
<div class="form-group">
<label>Valor Atual</label>
<form:input path="valorAtual" cssClass="form-control" />
</div>
<form:hidden path="pessoa" cssClass="form-control" value="${pessoa}"/>
<button type="submit" class="btn btn-primary">Cadastrar</button>
</form:form>
When I use the form in this way, I receive the error "description The request sent by the client was syntactically incorrect." I figured out that the problem is in this line, because when I delete, the form post ok:
<form:hidden path="pessoa" cssClass="form-control" value="${pessoa}"/>
Nevertheless, if I delete this line, the program doesn't save the idPessoa as a foreign key, this field is null. I would like to know how to pass an entire object in my JSP form. The post method is:
#RequestMapping(method=RequestMethod.POST)
public ModelAndView gravar(ContaCorretora contaCorretora) {
contaCorretoraDao.gravar(contaCorretora);
return new ModelAndView("pessoa/listageral");
}
all the DAO's methods are okay.
You only need to send the primary key of pessoa to the form.
Change the form attribute
<form:hidden path="pessoa.idPessoa" cssClass="form-control" value="${model.pessoa.idPessoa}"/>
Before persisting the ContaCorretora, make sure you get the Pessoa object from db.
#RequestMapping(method=RequestMethod.POST)
public ModelAndView gravar(ContaCorretora contaCorretora) {
contaCorretora.setPessoa(pessoaDao.find(contaCorretora.getPessoa().getIdPessoa()));
//I escaped null check and not found exceptions, you should apply some logic to take care of that
contaCorretoraDao.gravar(contaCorretora);
return new ModelAndView("pessoa/listageral");
}
Using Entities as form model is not a good approach. Persistance layer should not be on the MVC layer.
In order to pass Java object from your Controller
#RequestMapping(method=RequestMethod.POST)
public ModelAndView gravar(ContaCorretora contaCorretora) {
ModelAndView mav = new ModelAndView("pessoa/listageral");
// retrieve object from DAO
Object myObj = Dao.find(id);
// Put object into model map
mav.addObject("myObj", myObj);
// return model and view
return mav;
}
In JSP you can refer to object using ExpressionLanguage syntax
${myObj}