I have a table which is populated via a custom select statement to a database.
This has previously worked but now it is not displaying any values, not even the defaults.
I have created the table headings and here is the content declaration in the HTML:
<tr th:each="user : ${listUser}">
<td>
<a th:href="#{/editUser(user_id=${user.user_id})}">
<span th:text="${user.user_id}">Default ID</span>
</a>
</td>
<td th:text="${user.username}">Default username</td>
<td th:text="${user.email_address}">Default email</td>
<td th:text="${user.role_code}">Default role code</td>
<td th:text="${user.enabled_ind}">Default enabled</td>
<td>Default enabled</td>
</tr>
Here are the declarations in the Web Controller (The problems started when I added #GetMapping and #PostMapping, it seems to be ignoring #RequestMapping.
#GetMapping("/admin")
public String greetingForm(Model model) {
model.addAttribute("searchuser", new Searchuser());
return "admin";
}
#PostMapping("/userresults")
public String greetingSubmit(#ModelAttribute Searchuser searchuser) {
return "userresults";
}
#RequestMapping(value = "/userresults")
public ModelAndView listUser(ModelAndView model) throws IOException {
List<User> listUser = userDAO.loadAllUser();
model.addObject("listUser", listUser);
model.setViewName("userresults");
return model;
}
I know the SQL method is working as I have previously called it from another page.
Try this table structure for displaying your data.
<table border="1" style="width: 300px">
<tr>
<th>User name</th>
<th>Default Heading</th>
</tr>
<tr th:each="user : ${listUser}">
<td th:text="${user.username}">Default username</td>
<td>Default enabled</td>
</tr>
</table>
PS: I tested your code with the above table structure and both #GetMapping and #RequestMapping is working fine. Also make sure the listUser has atleast one User otherwise even the default won't be displayed.
Related
I'm trying to automatically update view (here list named emprunts) after insert into my database. I use Springboot, H2, JPA, Thymeleaf, ...
There is a way to do it? Or have I to refresh the page with Get request after the insert ?
Thanks a lot!
HTML / View
...
<div id="collapseThree" class="collapse" aria-labelledby="headingThree" data-parent="#accordionEmprunts">
<div class="card-body">
<table class="table">
<thead>
<tr>
<th scope="col">Usager</th>
<th scope="col">Exemplaire</th>
<th scope="col">Date de rendu</th>
<th scope="col">Statut</th>
</tr>
</thead>
<tbody>
<th:block th:each="emprunt : ${emprunts}">
<tr>
<!--/*#thymesVar id="emprunt" type="bibliotheque.model.Emprunt"*/-->
<td th:text="${emprunt.getUsager().getMail()}"></td>
<td th:text="${emprunt.getExemplaire().getOeuvre().getTitre()}"></td>
<td th:text="${emprunt.getDaterendu()}"></td>
<td th:text="${emprunt.getStatut()}"></td>
</tr>
</th:block>
</tbody>
</table>
</div>
</div>
...
Controller
#PostMapping
public ResponseEntity<?> newEmprunt(HttpEntity<String> infoEmprunt) throws IOException {
...
repository.save(object);
return new ResponseEntity<>(HttpStatus.CREATED);
}
If your view technology is thymeleaf then return html page instead of returning ResponseEntity(because response entity will return data in json format) and add data in model attribute.
There is a way to do it? Or have I to refresh the page with Get request after the insert ?
No need to refresh page just return html page from controller like below.
Emprunt emprunt = repository.save(object);
model.addAttribute("emprunt", emprunt);
return "show"; //show.html page
<table class="table">
<tr>
<th>Name</th>
</tr>
<tr th:each="recipe : ${recipes}">
<td th:text="${recipe.Name}"></td>
<td>
<span th:each="recipe,iterStat : ${recipes}">
</span>
</td>
<td>
<a th:href="#{/recipe/food/{id}(id=${recipe.id})}">view</a>
</td>
</tr>
I am trying to click this link above, utilizing this controller
#RequestMapping(value="recipe/food/{id}", method = RequestMethod.POST)
public String viewRecipe(#PathVariable int id, Model model){
model.addAttribute("name", recipeDao.findOne(id));
model.addAttribute("recipeText", recipeDao.findOne(id));
return "Recipes/food" ;
}
to display a single item, based on its id here
<table class="table">
<tr>
<th>Name</th>
</tr>
<form method ="post" th:action="recipe/food/{id}" th:object=${recipe}">
<tr th:each="recipe : ${recipes}">
<td th:text="${recipe.name}">text</td>
<td th:text="${recipe.recipeText}">text</td>
</tr>
<span th:errors="*{recipeText}" class="error"></span>
</form>
however i only get a 404, but the url information is correct
When you click the link it will execute a GET-request, so try changing the method in the Controller to method = RequestMethod.GET or simply remove method = RequestMethod.POST.
Update:
The part of the food template that is in the third code snippet is looping over a list named recipes, but the Controller method isn't adding a list as an attribute to the model only "name" and "recipeText". What you want is probably the template to display the recipe that you clicked the link for? Something like <h4 th:text="${name}"></h4> <span th:text="${recipeText}" />
In my application the user is show a list of exam objects and they select one to edit.
When they click the edit link it brings them to a HTML page where the URL contains that exams ID.
I would like to know how to pass the id of the exam to the controller.
I'm getting this error: "Missing URI template variable 'id' for method parameter of type Long"
I would also like to know how to make existing values appear in the forms text boxses.
HTML allSubjects.html where the user selects a subject to edit: (this all works)
<h4> exams:</h4>
<div th:each="exam : ${subject.exam}">
<h4 th:text="${exam.examTitle}"/>
<a th:href="#{/editExam.html(id=${exam.examId})}">Edit Exam</a>
Edit exam HTML:
<form action="#" th:action="#{/editExam.html{examId}}" th:object="${exam}" method="put">
<table>
<tr>
<td> Exam Title:</td>
<td><input type="text" th:field="*{examTitle}" th:text="${exam.examTitle}"/></td>
<!-- <td th:if="${#fields.hasErrors('examTitlee')}" th:errors="*{examTitle}">error message</td> -->
</tr>
<tr>
<td> Exam grade worth </td>
<td><input th:field="*{examGradeWorth}" /></td>
<!-- <td th:if="${#fields.hasErrors('examGradeWorth')}" th:errors="*{examGradeWorth}">error message</td> -->
</tr>
<tr>
<td>examGradeAchieved</td>
<td><input th:field="*{examGradeAchieved}"/></td>
</tr>
<tr>
<td><button type="submit">Submit post</button></td>
</tr>
</table>
</div>
</form>
My controller:
#RequestMapping(value = "/editExam.html{examId}", method = { RequestMethod.GET, RequestMethod.PUT })
public String editExam(#ModelAttribute("exam") #PathVariable(value = "id")Long examId, #RequestBody Exam exam,Model model, BindingResult result) {
examRepository.findOne(examId);
model.addAttribute("examTitle", exam.getExamTitle());
model.addAttribute("examGradeWorth", exam.getExamGradeWorth());
model.addAttribute("examGradeAchieved", exam.getExamGradeAchieved());
exam.setExamTitle(exam.getExamTitle());
exam.setExamGradeWorth(exam.getExamGradeWorth());
exam.setExamGradeAchieved(exam.getExamGradeAchieved());
examRepository.save(exam);
return "editExam";
}
WHen I try to run all the above code just to see if the form displays I get the following error: Missing URI template variable 'id' for method parameter of type String
I am following given link to submit table data to be saved in database
http://viralpatel.net/blogs/spring-mvc-multi-row-submit-java-list/
But the difference between given link and my implementation is that the front-end of link uses JSTL (JSP) while i am using Thymeleaf (HTML)
Below are the files being used
HTML Form :
<form method="POST" th:action="#{/updateAllRules}" th:field="${ruleForm}">
<table>
<thead>
<tr>
<th>S No</th>
<th>Title</th>
<th>Body</th>
</tr>
</thead>
<tbody>
<tr th:each="ruleModel,iteration : ${allRules}">
<td th:text="${ruleModel.id}"></td>
<td><input type="text" th:name="${'rule'+iteration.index+'.title'}" th:value="${ruleModel.title}"></td>
<td><input type="text" th:name="${'rule'+iteration.index+'.body'}" th:value="${ruleModel.body}"></td>
</tr>
</tbody>
</table>
<br>
<input type="submit" value="Update All">
</form>
Model Class :
public class Rule {
private Integer id;
private Date timestamp;
private String title;
private String body;
// constructor and Getter/Setters
}
Form Class :
public class RuleForm {
private List<Rule> rule;
public List<Rule> getRule() {
return rule;
}
public void setRule(List<Rule> rule) {
this.rule = rule;
}
}
Controller Method :
#RequestMapping(value = "/updateAllRules", method = RequestMethod.POST)
public String updateAllRules(#ModelAttribute("ruleForm") RuleForm ruleForm) throws IOException
{
System.out.println(ruleForm); // this prints com.web.model.RuleForm#235f9fcb
System.out.println(ruleForm.getRule()); //this prints null
return "redirect:/admin";
}
Please let me know what i am missing.
UPDATE 1:
Made changes as suggested. My new HTML form is as below
<form method="POST" th:action="#{/updateAllRules}" th:object="${ruleForm}">
<table>
<thead>
<tr>
<th>S No</th>
<th>Title</th>
<th>Body</th>
</tr>
</thead>
<tbody>
<tr th:each="rule,iteration : ${ruleForm}">
<td th:field="*{rule[__${iteration.index}__].id}"></td>
<td><input type="text" th:field="*{rule[__${iteration.index}__].title}"></td>
<td><input type="text" th:field="*{rule[__${iteration.index}__].body}"></td>
</tr>
</tbody>
</table>
<br>
<input type="submit" value="Update All">
</form>
On making these changes following exception is being received when the page loads.
org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'rule' cannot be found on object of type 'java.util.ArrayList' - maybe not public?
Please see that i am sending original list in model attribute "ruleForm" on page load. Once page loads the data and user make changes , i want to POST complete table back to controller.
Forms should have a th:object, rather than a th:field:
<form method="POST" th:action="#{/updateAllRules}" th:object="${ruleForm}">
Instead of using th:name and th:value, you should instead be using th:field which does both of those for you. Fields also should be specified using the *{...} syntax, which assumes the th:object automatically.
<input type="text" th:field="*{rule[__${iteration.index}__].title}" />
Everything else looks correct to me.
I have tried to send a parameter from this thymleaf page
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Email</th>
<th>Send Invoice</th>
</tr>
</thead>
<tbody>
<tr class="table-row" th:each="p : ${POList}">
<td th:text="${p.email}"></td>
<td>
<form style='float:left; padding:5px; height:0px' th:object="${p}" th:method="post" th:action="#{/dashboard/makeAndSendInvoice/{email}(email=${p.email})}">
<button class="btn btn-default btn-xs" type="submit">Send Invoice</button>
</form>
</td>
</tr>
</tbody>
and then I tried to receive the parameter (email) using this code
#RequestMapping(method=POST, path="/makeAndSendInvoice/{email}")
public void makeAndSendInvoice(#PathVariable("email") String email) throws Exception {
System.out.println("Invoice is sent to..................."+email);
}
The problem is when the value of p.email is something like myemail#gmail.com
what I receive in the method makeAndSendInvoice is only myemail#gmail
and it does not send me the .com part
How can I fix it?
(email=${p.email}) means , you are passing a query parameter.
So, how can you be able to catch the query param value using path variable?
We can use #RequestParam to catch the queryparam value in Spring
Try the below java code :
#RequestMapping(method=POST, path="/makeAndSendInvoice/{email}")
public void makeAndSendInvoice(#RequestParam("email") String email) throws Exception {
System.out.println("Invoice is sent to..................."+email);
}
The period in ".com" will need to be encoded to be used in the url to prevent it being parsed as the suffix
Your HTML:
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Email</th>
<th>Send Invoice</th>
</tr>
</thead>
<tbody>
<tr class="table-row" th:each="p : ${POList}">
<td th:text="${p.email}"></td>
<td>
<form method="post" th:action="#{/dashboard/makeAndSendInvoice/__${p.email}__} ">
<button class="btn btn-default btn-xs" type="submit">Send Invoice</button>
</form>
</td>
</tr>
</tbody>
Your controller
#RequestMapping(value = "/dashboard")
#Controller
public class testController {
...
#RequestMapping(value = "/makeAndSendInvoice/{email}", method = RequestMethod.POST)
public ModelAndView makeAndSendInvoice(#PathVariable String email, ModelAndView mav) {
return mav; // <- Break point, debug !!
}
}