In my Controller I have
#RequestMapping(value="/getCounties", method = {RequestMethod.GET},produces=MediaType.Application_JSON_VALUE)
public #Responcebody List<Counties>(#RequestParam String province){
List<Counties> county = this.xService.getCounties(county);
return county;
}
This method send the province chosen in the form down to the repository and join on the counties within that province.
In my dropdown on the form how do I return these values into the dropdown.
I currently have
<tr>
<td>
<form:select path="cdGcd" class="textbox" onclick="getCounty()">
<form:option value="-" label="Please Select"/>
<form:options path="county" items='${county}' itemValue = "countycode" itemLabel="countydescription"/>
</form:select>
</td>
</tr>
You can not return List directly form controller.
For passing data from controller to JSP you need to add data in Model and return respective JSP page.
So you need to change your method to,
#RequestMapping(value="/getCounties", method = {RequestMethod.GET})
public String getCountries(#RequestParam String province, Model model){
List<Counties> county = this.xService.getCounties(county);
model.addAttribute("county",county);
return "jsp page";
}
If you want to achieve this using AJAX then,you need to return JsonObject from controller.
Related
Please help me to solve this problem: I have no idea how to transfer data from thymeleaf view to controller, that expected data as a hash map? So let me explain in more detail.
I have next pojo, that is used as a wrapper for my hashMap data. It looks like this:
public class DTDays {
private Map<Driver, String> driversDays = new HashMap<>();
public Map<Driver, String> getDriversDays() {
return driversDays;
}
public void setDriversDays(Map<Driver, String> driversDays) {
this.driversDays = driversDays;
}
}
Controller has method with parameter model attribute and another pojo:
#RequestMapping(value = "/go", method = RequestMethod.POST)
public String advanced(#ModelAttribute DTDays dtDays,
#RequestParam(name = "tourId") Long tourId, Model model){
// make some business logic with provided data
return "redirect:/tours/advanced";
}
Here I debugged and dtDays is not null, but map property is empty, also tourId is worked as expected, I can get right value.
Now to the problem, view:
<body>
<div style="margin-left: 20px;">
<h1 th:text="${tour.tittle}"></h1>
<p>Add tour interval for drivers</p>
<form id="driverIntervals" th:action="#{/advanced/go}" th:object="${driversDays}" method="post">
<table>
<tr>
<td>Drivers:</td>
<td>Date:</td>
</tr>
<tr th:each="d: ${attachedDrivers}">
<td th:text="${d.id+' '+d.fullName}" >
<input type="hidden" th:value="${d.id}" >
</td>
<td>
<input type="text" placeholder="Pick days" th:name="days"/>
</td>
</tr>
</table>
<input type="hidden" th:name="tourId" th:value="${tour.id}"/>
<button type="submit">Confirm</button>
</form>
</div>
</body>
View looks like this:
What should i write in view to submit data? In my case Driver is a key of the map and user entered data in related input field will be a value of a map.
I already know how to submit List, by using select-option in a view:
<select th:name="drivers2attach" multiple="multiple" id="attachDrivers">
<!--/*#thymesVar id="drivers" type="java.util.List<stanislav.tun.novinomad.picasso.persistance.pojos.Driver>"*/-->
<option th:each="d : ${drivers}" th:value="${d.id}"
th:text="${d.getId()+' '+d.fullName}">
</option>
</select>
and #RequestParam List list in controller:
#RequestMapping(value = "/save", method = RequestMethod.POST)
public ModelAndView addTourAction(#ModelAttribute("tour") Tour tour,
#RequestParam(required = false, name = "drivers2attach") List<Long> drivers2attach)
But how to deal with map?
In case with list data is auto populated. In map only keys is prepopulated, this is count of drivers, and now i expect user input for each driver as a key value.
In researching of answers i already read these sources:
How to bind an object list with thymeleaf?
Send list object from thymeleaf to controller
How do I load HashMap and ModelandView object values using Thymeleaf in a Spring Boot application?
Thymeleaf Map Form Binding
http://forum.thymeleaf.org/How-to-use-Map-lt-String-String-gt-with-Spring-and-Thymeleaf-forms-td4028666.html
http://forum.thymeleaf.org/How-to-use-method-POST-with-a-complex-Hashmap-lt-Object-list-lt-Object-gt-gt-td4031257.html
Thymeleaf Map Form Binding
Use HashMap as Form Backing Bean Spring MVC + ThymeLeaf
etc.
But didn't helps. Somewhere in this links I found out that I should use some wrapper to do it, but again no idea why it not works, or what should I do additionally for make it working. Maybe I generally make wrong logic and to submit data as hashmap I shall convert data to list first and then somehow get map from it in controller?
Sorry for creating duplicate question, finally i found solution by following this answer on stackoverflow
i wrote little project for test it and it works. So i was on right way in controller with a wrapper. I missed only view map representation and syntax;
Finally view will looks like this:
view
here is view source code:
<form th:action="#{/save}" th:object="${form}" method="post">
<h1>Welcome</h1>
<div th:each="property : ${form.properties.entrySet()}">
<div class="form-group">
<label th:for="*{properties['__${property.key}__']}" th:text="${property.key}">Property</label>
<input type="text" class="form-control" th:field="*{properties['__${property.key}__']}" />
</div>
</div>
<button type="submit">send to controller</button>
and controller:
#PostMapping("/save")
public ModelAndView save(#ModelAttribute(name = "form") MapWrapper form){
var mav = new ModelAndView();
mav.setViewName("index");
mav.addObject("mapWrapper", form);
var map = form.getProperties();
System.out.println("Size of map = "+map.size());
for (Long id : map.keySet()) {
System.out.println("Key: "+id+"; Value: "+map.get(id));
}
return mav;
}
and output is :
output
P.S. reason of asking here is that i stuck on this problem for about 2 weeks, I despaired, but found solution after create a question.
so i want to display single row by its id on spring mvc
i have this dao:
public Message getMessageById(int id){
String sql="select * from tb_message where id_message=?;";
return template.queryForObject(sql, new Object[]{id},new BeanPropertyRowMapper<Message>(Message.class));
}
and this is my controller:
#RequestMapping(value="/replymessageto/{id}")
public String viewforreply(#PathVariable int id, Model m){
Pesan currentmessage=dao_send_message.getMessageById(id);
m.addAttribute("command", currentmessage);
return "viewcurrentmessage";
}
i can display the value if i use this on my jsp:
<form:form>
<form:input type="text" path="message_title" name="message_title" class="form-control"/>
</form:form>
but what i want is to show the value only on <p></p> tag
I have a data base which contains some items. I want to create a form which edits item with some id. I did it, form opens fine. Adress is /itemproject/edit_item/{id} Problems start when I'm trying to activate POST method. Instead of directing me to page with item list (/itemproject/view_items) programm sends me to /itemproject/edit_item/edit_item. itemproject is context path (for example).
#RequestMapping(value = "/edit_item/{id}", method = RequestMethod.GET)
public String editItem(#PathVariable("id") Integer id, Model model) {
Item item;
item = dbService.findItem(item).get(0);
model.addAttribute("item", item);
return "edit_item";
}
#RequestMapping(value = "/edit_item/{id}", method = RequestMethod.POST)
public String editItemComplete(#PathVariable("id") Integer id, #ModelAttribute("item") Item item, Model model) {
dbService.updateItem(item);
model.addAttribute("items",dbService.findAllItems());
return "view_items";
}
dbService works with data base.
I want that programm sent me to list of all items after ediding chosen item and updating it in database.
Here is example of edit form (url: /itemproject/edit_item/{id}
<spring:url value="edit_item" var="formURL"/>
<form:form action="${formURL}"
method="post" cssClass="col-md-8 col-md-offset-2"
modelAttribute="item"
>
<div class="form-group">
<label for="item-stuff">Stuff</label>
<form:input id="item-stuff"
cssClass="form-control"
path="stuff"/>
</div>
<button type="submit" class="btn btn-default">Edit item</button>
</form:form>
This is how my item list page looks (url: /itemproject/view_items)
<body>
<table class="table table-hover">
<tbody>
<tr>
<th>Stuff</th>
</tr>
<c:forEach items="${items}" var="item">
<tr>
<td>${item.stuff}</td>
</tr>
</c:forEach>
</tbody>
</table>
</body>
From Spring docs:
In Spring MVC you can use the #PathVariable annotation on a method
argument to bind it to the value of a URI template variable
That means that #PathVariable annotation is suitable when you use the GET method because when you use GET method you can pass your query string.
Instead, try to use #RequestBody in order to try to bind your POST HTTP body message to your parameter
For example:
#RequestMapping(value = "/edit_item", method = RequestMethod.POST)
public String editItemComplete(#RequestBody String body) {
//in here you'll have to pull the body content
return "view_items";
}
Let's say that you're sending an Integer id on HTTP POST body, then you can pull the data from the body like this:
#RequestMapping(value = "/edit_item", method = RequestMethod.POST)
public String editItemComplete(#RequestBody String body) {
ObjectMapper objectMapper = new ObjectMapper();
try {
idJson = objectMapper.readTree(body).path("id").asInt();
} catch (IOException e) {
e.printStackTrace();
}
return "view_items";
}
assuming that you're sending json from client to service.
Rather than loading the items and returning the view_items template, you can return "redirect:/itemproject/view_items" and that will cause your handler for view_items to be invoked, which will load the items etc.
register.jspx
<form action="register" id="user" method="POST">
<form:select path="factory">
<form:options itemValue="id" itemLabel="name" items="${factory}" />
</form:select>
</form>
model
public class Factory {
#Size(max = 255)
private String name;
}
controller
#RequestMapping(method = RequestMethod.POST, produces = "text/html",value = "/register")
public String UsersController.register(#Valid Users users,UserData userData,Factory factory,BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
if (bindingResult.hasErrors()) {
Logger.getGlobal().log(Level.WARNING, bindingResult.getAllErrors().get(0).toString());
populateRegisterForm(uiModel, users);
return "userses/register";
}
uiModel.asMap().clear();
userData.setFactory(factory);
userData.persist();
users.setUserData(userData);
users.persist();
return "redirect:/userses/" + encodeUrlPathSegment(users.getId().toString(), httpServletRequest);
}
and html output
<select>
<option value="1">aa</option>
<option value="2">bbbbbbbbbbbb</option>
</select>
Select tag haven't name veriable in html output. but i edited jspx file with path="factory"
You need to enclose your form:select within a Spring form:form, and not just an ordinary form.
I'm pretty sure your JSP won't compile after you make that change - it looks like you may have other errors, but hard to tell without seeing the rest of your domain. Can you also add the controller handler/action that is called to produce the form view.
Hi I am wondering how to create dynamic drop down lists that get refined after the selection of a value in another drop down list.
For example, if I have two drop down lists Customer Name and Customer Country and I select a certain Customer Name, I only want to see the corresponding Customer Countries.
Using a query:
public List<Customer> getAllCustomerCountries(customerName) {
return this.sessionFactory
.getCurrentSession()
.createQuery(
"select distinct customerCountry from Customer where
customerName=:name").setParameter("name", customerName)
.list();
}
I can get the corresponding Countries but how do I pass on the input value customerName when it is selected in its own drop down list?
here is the code I'm using for the customerName drop down list:
<tr>
<td>Customer Name</td>
<td><form:select path="customerName">
<form:option value="" label="--- Select ---" />
<form:options items="${customerNameList}" />
</form:select>
</td>
<td><form:errors path="customerName" cssClass="error" /></td>
</tr>
In the controller the lists are populated by:
model.addAttribute("customerNameList",
customerService.listAllCustomerNames());
model.addAttribute("customerCountryList",
customerService.listAllCustomerCountries());
Thank you for your help!
/D
Update
Ok, so I have now used JavaScript to submit the page when a CustomerName is chosen so that a refined list list is loaded for the CustomerCountry drop down box.
Here is part of the jsp including the script:
<script>
function repopulate(){
document.getElementById("hasId").value ="true";
alert("You selected : " + document.getElementById("hasId").value);
document.deliveryForm.submit();
}
</script>
<!-- ... -->
<tr>
<td><form:hidden id="hasId" path="hasCustomerName" value="false"/></td>
</tr>
<tr>
<td>Customer Name</td>
<td><form:select path="customerName" onChange="repopulate()">
<form:option value="" label="--- Select ---" />
<form:options items="${customerNameList}" />
</form:select>
</td>
<td><form:errors path="customerName" cssClass="error" /></td>
</tr>
And here is part of the controller:
#RequestMapping(value = "/add", method = RequestMethod.GET)
public String getDelivery(ModelMap model) {
DeliveryDto deliveryDto = new DeliveryDto();
model.addAttribute("deliveryDtoAttribute", deliveryDto)
model.addAttribute("customerNameList",
customerService.listAllCustomerNames());
model.addAttribute("customerCountryList", null);
return "new-delivery";
}
#RequestMapping(value = "/add", method = RequestMethod.POST)
public String postDelivery(
#ModelAttribute("deliveryDtoAttribute") #Valid DeliveryDto deliveryDto,
BindingResult result, ModelMap model) {
if (deliveryDto.getHasCustomerName() == "true"){
model.addAttribute("deliveryDtoAttribute", deliveryDto);
model.addAttribute("customerNameList",
customerService.listAllCustomerNames());
model.addAttribute("customerCountryList",
customerService.listAllCustomerCountries(deliveryDto.getCustomerName()));
return "new-delivery";
}
if (result.hasErrors()) {
model.addAttribute("deliveryDtoAttribute", deliveryDto);
model.addAttribute("customerTargetIdList",
customerService.listAllCustomerTargetIds());
model.addAttribute("customerNameList",
customerService.listAllCustomerNames());
model.addAttribute("customerCountryList",
customerService.listAllCustomerCountries(deliveryDto.getCustomerName()));
}
Delivery delivery = new Delivery();
/* A bunch of setters and to set the values in the delivery object that will be saved */
deliveryService.createDelivery(delivery);
return "redirect:/home";
}
The problem I'm having is that the post method doesn't stop after the first if-loop and checks for errors and then tries to save the delivery as soon as i select a value in the CustomerName drop down box.
Does anyone know how I can make it so that it only continues on to check for errors (2nd if-loop) and save the delivery when I hit the submit button in the jsp page?
You must add a JavaScript event listener to the select box, which will do one of the following:
submit the form (after modifying its action attribute), in order for the controller to redisplay the same page but with a different set of countries
send an AJAX request to the controller with the customer name, and dynamically populate the select box with the set of countries contained in the response. The response could be a JSON array of countries, or an HTML snippet containing the new options of the select box, for example.