Spring MVC: simple validation without #ModelAttribute / "command object" - validation

How to validate a simple form (one input field) and show errors without providing a command object ? My simple form is:
<form id="verify" action="check.html">
<input name="code"/>
<form:errors path="code" />
<input type="submit" value="ok" />
</form>
Controller handler method below. I need to generate error message and show in place of form:errors
#RequestMapping("/check.html")
public String check(#RequestParam(value="code") String code) {
if(!isGood(code)) {
// How to bind some error messages for `code` ?
return "fail"; // fail page
}
return "ok";
}

In short words, <form:errors> doesn't work without <form:form> and other #ModelAttribute-related functionality. If you want the simpliest solution, you can export error message as a normal model attribute instead of using <form:errors>:
#RequestMapping("/check.html")
public String check(#RequestParam(value="code") String code, ModelMap model) {
if(!isGood(code)) {
model.put("codeError", "...")
return "fail"; // fail page
}
return "ok";
}
<form id="verify" action="check.html">
<input name="code"/>
<c:out value = "${codeError}" />
<input type="submit" value="ok" />
</form>

Related

How to pass model value in thymeleaf input text

I have data in a Model object and I want to put that into the input field in my Thymeleaf template, such that if the value is null, nothing will be displayed and otherwise, the input will have the value inside it. I tried this but this is not working.
<input id="first_name" type="text" name="firstName" placeholder="First" value=${accountInfo.firstName} maxlength=31 required>
I passed the values into the model object inside the java exception handler like so:
#ExceptionHandler(value=SignupFormException.class)
public String handle(HttpSession session, SignupFormException ex, Model response) {
response.addAttribute("accountInfo", (Account) session.getAttribute("accountToRegister"));
response.addAttribute("Error", ex.getMessage());
session.invalidate();
return "redirect:/signup";
}
How to fetch the attributes from the accountInfo object I passed in my model in my thymeleaf template?
Update:
Now it is working but not the first time the page is accessed when there is no model object. Following is the code:
My thymeleaf form:
<form action="/signup_do" th:object="${accountInfo}" method="post">
<input id="first_name" type="text" name="firstName" placeholder="First" th:value=*{firstName} maxlength=31 required>
Controller:
#PostMapping("/signup_do")
public String register(Account account, HttpSession session) {
session.setAttribute("accountToRegister", account);
accountManagement.accountRegistration(account);
return "Success";
}
There is a account registration service that throws SignupFormException which is handled by:
#ExceptionHandler(value=SignupFormException.class)
public String handle(HttpSession session, SignupFormException ex, Model response) {
response.addAttribute("accountInfo", (Account) session.getAttribute("accountToRegister"));
response.addAttribute("Error", ex.getMessage());
session.invalidate();
return "redirect:/signup";
}
And only now do I have a model object with properties for the thymeleaf template...
change "value" to "th:field"
OR
change "value" to th:value="${accountInfo.firstName}"
<form action="#" th:action="#{/yourURL}" th:object="${accountInfo}" method="post">
<input id="first_name" type="text" name="firstName" placeholder="First" th:field=*{firstName} maxlength=31 required>
<input type="submit" class="btn btn-primary" value="Submit">
</form>

Spring & JSP: Get value from certain input using spring controller

Can somebody help me to get value from certain input using spring controller.
I have 2 input data, and I just need a value from one of these inputs:
<input type="text" name="data01" />
<input type="text" name="data02" />
I just want to retrieve a value from "data01".
I just have used
(HttpServletRequest) request.getParameter("data01")
Or
#RequestParam(value="data01") Integer data01
but the value is null.
Can somebody help me
EDIT:
jsp:
<table>
<tr>
<input type="text" name="data01" />
<input type="text" name="data02" />
</tr>
</table>
controller:
#RequestMapping(value = "/user", method=RequestMethod.GET)
public String showAllData(ModelMap model, HttpServletRequest request) {
String retrievedData = request.getParameter("data01");
System.out.println("data= " + retrievedData);
model.addAttribute("data", new data());
return "data";
}
The retrievedData value is null.
You should be able to get the parameter using this method
<form action="/user" method="get">
<table>
<tr>
<input type="text" name="data01" />
<input type="text" name="data02" />
<input type="submit" value="submit"/>
</tr>
</table>
</form>
and in the controller
#RequestMapping(value = "/user", method=RequestMethod.GET)
public String showAllData(String data01, ModelMap model) {
// your logic here
}
and from the code you have posted. You are casting the parameter to HttpServletRequest
request.getParameter("data01") //returns String as default.
Integer.parseInt(request.getParameter("data01");
From your comment at #user1516735 answer, you cannot use it outside of the form tag. Unless you include it in the parameter from ajax or append the value of "name01" in the url as /user?name01=value
You will get the value of data01 by using the below code:
request.getParameter("data01");
Here request is of type HttpServletRequest. Make sure your input control is inside form tag.

How to pass only string in thymeleaf form?

I have a little problem. When I have an object with some fields, it's easy to pass these fields through form:
Controller:
#RequestMapping("/")
public String hello(Model model) {
model.addAttribute("test", Test);
return "index";
}
html:
<form th:action="#{/process}" method="post" th:object="${test}">
<input type="text" th:field="*{value}"/>
<input type="submit" />
</form>
But what if I don't want to have an object and pass only string? Something like that:
Controller:
#RequestMapping("/")
public String hello(Model model) {
model.addAttribute("test", "test string");
return "index";
}
html:
<form th:action="#{/process}" method="post">
<input type="text" th:field="${test}"/>
<input type="submit" />
</form>
doesn't work.
Thanks for help!
For next question in comments:
index.html:
<form th:action="#{/process}" method="post">
<textarea th:text="${sourceText}"/>
<input type="submit" />
ggg.html:
<textarea th:text="${sourceText}"/>
controller:
#RequestMapping("/")
public String hello(Model model) {
model.addAttribute("sourceText", "asdas");
return "index";
}
#RequestMapping("/process")
public String process(Model model, #ModelAttribute(value = "sourceText") String sourceText) {
return "ggg";
}
th:field is used only if you declare object like th:object.
<form th:action="#{/process}" method="post">
<input type="text" th:value="${sourceText}" name="sourceText"/>
<input type="submit" />
</form>
Spring matches values by "name" attribute. Just catch it with #RequestParam in controller like
#RequestMapping("/process")
public String process(Model model, #RequestParam String sourceText) {
return "ggg";
}
According how Spring MVC works you can't use a string as an object in a form, you need an object to encapsulate that string, because the form structure is Object and then any field linked to it.
In your case, I would create a view form object for those common situations, something like formView with the String attribute text. And you could use the same object in similar situations.
Other option if you don't want to create this extra object, you could send the data by AJAX, and build the data array to send to the controller in javascript.
Personally I would go for the first option, is more reusable.
Hope this help you

Thymeleaf - Button click to call http delete method

I would like to call the url via http delete method. I tried th:onclick and th:action but not working.
html code:
<button id="delete" name="delete" th:onclick="#{'/foos/{id}'(id=${foo.id})}" th:method="delete">Delete</button>
controller code:
#RequestMapping(value="/foos/{id}", method = RequestMethod.DELETE)
#ResponseBody
public String delete(#PathVariable String id) {
studentService.delete(id);
return "Successfully deleted";
}
I think you will need a form for your transaction. And also this hidden input field.
<form action="#" th:action="#{'/delete/{id}'(id=${foo.id})}" th:method="delete" >
<input type="hidden" name="_method" value="delete" />
<button type="submit" id="submitButton"> </button>
</form>
The th:method="delete" creates the hidden input field automatically for you. If you add it manually as well you will have it twice. Check the source code.
I still got the POST Error message after the recommendations here. I found out Spring ignores those hidden fields by default. The solution is to activate it in your application.properties file:
spring.mvc.hiddenmethod.filter.enabled=true
My working code in my application looks like this:
Form:
<form action="#" th:action="#{'/books/delete/{id}'(id=${book.id})}" th:method="delete" >
<button type="submit" class="btn">
Delete
</button>
</form>
Controller:
#RequestMapping(value="/books/delete/{id}", method = RequestMethod.DELETE)
public String deleteBook(#PathVariable Long id) {
bookService.deleteBook(id);
return "books";
}

ASP.Net MVC3: how to send different values for same field?

How can I send to action of controller different values for same field? Which input parameters should I define in action? And how can I show url with different values of identical fields in querystring? I want to get such url: site.com/directory?metro=2&metro=3
Thanks!
Here's an example of how this would be done in the case of checkboxes. Note that you wouldn't see the same querystring parameter repeated in the case of a GET request. Instead you would see "?metros=1,3" if checkboxes 1 and 3 were checked.
HTML
<form action="http://site.com/directory" method="get">
<input type='checkbox' name='metros' value='1' />
<input type='checkbox' name='metros' value='2' />
<input type='checkbox' name='metros' value='3' />
</form>
Controller
public class DirectoryController : Controller {
public ActionResult Index(IEnumerable<int> metros) {
foreach (var metro in metros) {
// do something
}
return View();
}
}

Resources