I am trying to code an HTML form that sends data to a RESTful web service (managed with Spring) using select HTML element.
The REST has to create an object Event on my database.
The problem I find is that the #RequestParam in the REST comes empty even if my options' values are present.
This is my HTML form.
<form name="editForm" role="form" novalidate ng-submit="vm.save()">
<!-- other fields that works correct -->
<div class="form-group">
<label class="control-label" data-translate="businessRequestApp.event.participantsAdd" for="field_attendees">Attendees</label>
<select style="height: 300px;" multiple class="form-control" id="field_attendees" ng-model="vm.event.usersOnIt" ng-options="customUser as customUser.username for customUser in vm.customusers | orderBy:'id' track by customUser.id">
<option value="{{customUser.username}}" name="attendeesToParse"></option>
</select>
</div>
</form>
This is my REST.
#PostMapping("/events")
#Timed
public ResponseEntity<Event> createEvent(#RequestBody Event event, #RequestParam(value="attendeesToParse") List<String> participants) throws URISyntaxException {
//Some code that creates an object "Event" on my database
}
I am trying to fill a field List of String. Due to my business logic I can't insert it into Event's class, so I have to threat it separately.
Note that #RequestBody works correctly, the issue is only with #RequestParam that does not receive anything.
Thanks in advice for your time.
Options elements are never sent. Select's value is sent. Try to move the name="attendeesToParse" to the select itself.
If you need multiple values create a hidden input and store selected options into the field. Use the hidden input name to get values in the controller.
Related
I have an html page to edit a list of persons.
When the page is opened the controller gets the list of persons from the db and binds to the view.
That works fine.
Then the user edits the data and clicks save.
Now I need to submit the edited data of each person to the controller so that the controller can save the edits.
I'm trying to do that using #ModelAttribute ArrayList<Person> as shown below but it's not working.
The arraylist comes empty.
How do I do for the arraylist to come filled with all of the persons objects from the form?
View
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<form action="editperson" method="post">
<th:block th:each="person : ${personBind}">
Name:
<input type="text" th:value="${person.name}" />
</br></br>
Age:
<input type="text" th:value="${person.age}" />
</br></br>
</th:block>
</br></br>
<input type="submit" name="btnSaveEdit" value="Save"/>
</form>
Controller
#RequestMapping(value = "/editperson", params = "btnSaveEdit", method = RequestMethod.POST)
public String saveEditPerson(#ModelAttribute ArrayList<Person> personsList){
//save edit code here
return "editperson";
}
Spring MVC with Thymeleaf does indeed use model attributes to store data for the Thymeleaf pages. This guide shows how to load data from a form into the application. Try wrapping the ArrayList inside of a custom object and access the list via that object as a ModelAttribute rather than working with an ArrayList directly.
The saveEditPerson method should probably be named "saveEditPersons" since you are parsing a list of persons rather than just one.
My form is based on Thymeleaf, I am not using tables because it has many fields.
In the form I have 3 buttons, one is a submit and the others are links. With a link button I want to make a query using a parameter that sends a string to the controller.
I want to get the string that was passed in the URL to the controller and receive the data with an #RequestParam annotation.
I have no error messages, what happens is that the string reaches the controller empty.
This is my link button:
<a class="btn btn-success text-white btn-sm mr-3 " style="border-radius: 16px;" th:href="#{/config/item/items/select(productId=${item.productId})}">
Search
</a>
This is my text field where the user places the query:
<div class="col-2 form-group"
th:classappend="${#fields.hasErrors('item.productId')}? 'has-error':''">
<label for="productId"><strong>Item id </strong></label> <input
type="text" class="form-control" id="productId" name="productId"
th:field="${item.productId}">
</div>
And all this goes inside my form:
<form th:action="#{/config/item/items/save}" method="get"
th:model="${item}">
I have used these two but with no results:
th:href="#{'/config/item/items/select'+${item.productId}}"
th:href="#{|/config/item/items/select${item.productId}|}"
I have reviewed the documentation provided by Thymeleaf at: https://www.thymeleaf.org/doc/articles/standardurlsyntax.html, in chapter number nine.
And I have also seen tutorials but it doesn't work.
If you want to use the #RequestParam annotation you need to add a parameter in your link.
Your code should be something like:
th:href="#{select(productId=${item.productId})"
(According you added the object item to your template)
In your controller "select" you have to use the annotation #RequestParam to retrieve the info:
#GetMapping (path = "/select")
public String list(Model model,
#RequestParam(name = "productId") int productId) {
// rest of the code
}
When I get an entity "Product" in the controller, I have all the null data.
#GetMapping("/admin/product/delete")
public ModelAndView showProductDeletePage(
#RequestParam String productId
){
Long longId = Long.parseLong(productId);
Product product = productService.getProductById(longId);
ModelAndView modelAndView = new ModelAndView("/admin/product/delete");
modelAndView.addObject("product", product);
return modelAndView;
}
But, in the string
modelAndView.addObject("product", product);
I send a product to the form.
<div class="w3-container">
<form th:action="#{'/admin/product/delete?productId=' + ${product.getId()}}" method="post">
<h2>Delete product</h2>
<p>If you submit, product will be deleted irrevocably</p>
<div th:text = "${product.getProductName()}" class="w3-panel w3-card-4"><p>w3-card-4</p>
</div>
Cancel
<input class="w3-button w3-red" type="submit" value="Delete"/>
</form>
</div>
And, for example, in the strings
<div th:text = "${product.getProductName()}" class="w3-panel w3-card-4"><p>w3-card-4</p>
<form th:action="#{'/admin/product/delete?productId=' + ${product.getId()}}" method="post">
my app has not a problem and returns to the screen correctly data.
How is it possible?
An issue in it, that I cannot use the entity in the other cases. And in general - how is it possible??
Hibernate uses proxies for the entities and currently you are looking at the proxy. The proxy itself acts like a Product but doesn't contain the actual data. That is present in the handler.
If you click through on the handler you eventually will get to the actual Product instance.
Possible reasons are:
You may have different connection strings.
Your web application is not in running state.
You have cached data.
Its not possible in the way you are trying to describe the issue, add debugger/breakpoints to narrow down your issue.
My RequestController:
#Controller
#RequestMapping("/request")
public class RequestsController {
private static final Logger log = LoggerFactory.getLogger(TmtApplication.class);
#Autowired
RequestRepository requestRepository;
#Autowired
UsersRepository usersRepository;
#RequestMapping("/save")
String saveRequest()
{
Request requestObj = new Request(usersRepository.findOne(1L), new Date());
requestObj.setDescription("I got so bored");
requestObj.setStatus(false);
requestObj.setRequestDate(new Date());
requestRepository.save(requestObj);
return "index";
}
}
My button:
<input type="submit" value="Submit Request" style="display: block;">
I'm trying to get my button to fire off this request. What should I add to my HTML to initiate the call for /save?
Update:
Form:
<form action="/request/save" method="post" commandName="requestData">
<input type="text" id="dateInput" value="" style="display: none;"/>
<div style="width: 200px;"><input type="submit" value="Submit Request" style="display: block;">
</div>
</form>
Controller:
#RequestMapping(value = "/save", method = RequestMethod.POST)
String saveRequest(#ModelAttribute("requestData") Request requestData, Map<String, Object> map,
HttpServletRequest request)
{
Request requestObj = new Request(usersRepository.findOne(1L), new Date());
requestObj.setDescription(requestData.getDescription());
requestObj.setStatus(false);
requestObj.setRequestDate(requestData.getRequestDate());
requestRepository.save(requestObj);
return "save";
}
To get this to work using the spring code as-is, you must surround your tag with a form.
<form action="save">
<input type="submit" value="Submit Request" style="display: block;">
</form>
In addition, you must be calling this from the correct URL to get it to work. The form action can be relative to the page you're on, or relative to the root of the URL.
You have two options to hit the RequestMapping, which resolves to:
/request/save
One is to use a relative action. You'll have to serve your HTML up at this url:
{server:port}/request
and then your action should be:
"save"
The second option is to use an absolute path for the form action:
"/request/save"
Which will work from wherever your HTML is served on this server.
Summary
You need to submit something (the form), and tell it where to submit to (action). So you need to sync up your URL's, your form, and the submission endpoint.
Additionally, it is a good idea to specify the request method on your RequestMapping so that you can handle POST/GET separately. According to the Spring Documentation, the default behavior is to map ALL HTTP methods:
The above example does not specify GET vs. PUT, POST, and so forth,
because #RequestMapping maps all HTTP methods by default.
It's a good idea to specify a POST for a form submit.
#RequestMapping(value = "/save", method = RequestMethod.POST)
This is the direction you should go, since a form submit should be a POST action so that the contents of the form go in the request body, and eventually you will want it to take in fields from your form for the POST, and map them to objects in your Controller class.
A few Tips:
Consider using a Templating engine like Thymeleaf (which spring often has in their tutorials), or JSP+taglibs. Thymeleaf is a bit more lightweight, and if you use it, you'll have the benefit of doing things the way Spring has written a lot of their examples. See this tutorial for an example:
Spring Boot: Handling Form Submission
Alternatively if someone is just trying to test a Request Mapping, or you're just trying to verify that your MVC endpoint is doing what you think, it would be a lot simpler to use a tool like Postman (which I highly reccomend) to submit your requests. That would take a few variables out for you so you can focus on what you're trying to develop (A REST API?), rather than the testing setup.
So the question is like we manipulate the values of the form fields through servlets by using request.getParameter() can we do the other way round i.e set the form feild values fromthe servlet itself?
Basically what I am trying to do is to create a dropdown and some textboxes. the dropdown gets the ids from the database , when user selects a particular id, the text boxes should get filled with the other values from database for that id so the user can either edit them or leave unchanged accordingly.
For ex: The html code is:
<form action="GetValues">
<select name="ids"><option>1</option><option>2</option></select>
<input type="submit" value="Edit">
</form>
<form action="Save">
Product name:<input type="text" name="name" id="tb1"/></br>
Price:<input type="text" name="price" id="tb1"/>
<input type="submit" value="Save">
</form>
The Getvalues servlet establishes the database connection and gets the values of name and price from the datbase which I can do, but how to display those values in the two textboxes?
I can than make the Save.java servlet to get the values from textfields and update into the database.
I am not at all comfortable using JSP scriptlets. I want to do this using servlets only.
I know I could have created textboxes using the servlet itself but that won't work for me because that makes my jquery on the form die.
Like we do in javascript:
var x="hii";
document.getElementById("tb1").value=x;
Is there anything like this in Java too?
I know you requested no scriptlets, but IMO this is the easiest way to do it.
In your servlet, set a request attribute as such:
request.setAttribute("attributeName", attributeValue);
Then in your jsp, you can access the attributeValue like this:
<%= request.getAttribute("attributeName") >
Edit: For the followup question in the comment, here is how you can show the IDs in the select box using scriptlets:
First, set the list of IDs in the servlet:
List<String> idList = ...;
request.setAttribute("idList", list);
Then in your JSP, construct the select field as follows:
<select name="ids">
<%
List<String> idList = request.getAttribute("idList");
for(String id : idList) {
%>
<option><%=id></option>
<%
}
%>
</select>
. the dropdown gets the ids from the database , when user selects a particular id, the text boxes should get filled with the other values from database for that id so the user can either edit them or leave unchanged accordingly.
That is the perfect place to use a AJAX call. Please fire a AJAX request and get the values from Database.