Do Spring property editors only work on forms? - java

I'm working on a Spring application that simply searches a set of data for things that match some criteria. There are two main views: one is a simple form that lets the user configure search criteria, while the other displays the results as a table.
One of the search fields is a closed set of options (about 10). Lower down in the code, I want to handle this as an enum class. The web form includes a drop-down that allows the user to select an option from this set. I've used a form:select to do this, populated with a set of strings that describe the values.
To keep the presentation and business logic separate, the enum class musn't have any knowledge of these strings, so I've created a Property Editor to convert between the two. When I load the form, the select control is set to the string associated with the enum value I gave it; when the form is submitted, the string is converted back to my enum type. This is all working fine.
For the results page (which isn't a form), I simply add the data to be displayed to a ModelMap. At the moment, I have to explicitly convert my enum type to a string before I add it to the map. What I'd like to do is just add the enum to the map and have the property editor convert it for me in the background, like it does for the form. I can't work out how though. Is it possible to do this? Maybe I'm missing something really obvious?

You can use Spring Tablib
<%#taglib uri="http://www.springframework.org/tags" prefix="spring"%>
And use transform markup
<!--If you have a command which command name is account-->
<!--Default command name used in Spring is called command-->
<spring:bind path="account.balance">${status.value}</spring:bind>
Or
<spring:bind path="account.balance">
<spring:transform value="${account.balance}"/>
</spring:bind>
Or
<!--Suppose account.balance is a BigDecimal which has a PropertyEditor registered-->
<spring:bind path="account.balance">
<spring:transform value="${otherCommand.anotherBigDecimalProperty}"/>
</spring:bind>
About value attribute
The value can either be a plain value to transform (a hard-coded String value in a JSP or a JSP expression), or a JSP EL expression to be evaluated (transforming the result of the expression). Like all of Spring's JSP tags, this tag is capable of parsing EL expressions itself, on any JSP version.
Its API
Provides transformation of variables to String, using an appropriate custom PropertyEditor from BindTag (can only be used inside BindTag)
If you use MultiActionController i advice you to use a Dummy Command class as bellow
public class Command {
public BigDecimal bigDecimal;
public Date date;
/**
* Other kind of property which needs a PropertyEditor
*/
// getter's and setter's
}
Inside your MultiActionController
public class AccountController extends MultiActionController {
#Autowired
private Repository<Account, Integer> accountRepository;
public AccountController() {
/**
* You can externalize this WebBindingInitializer if you want
*
* Here it goes as a anonymous inner class
*/
setWebBindingInitializer(new WebBindingInitializer() {
public void initBinder(WebDataBinder dataBinder, WebRequest request) {
binder.registerCustomEditor(BigDecimal.class, new CustomNumberEditor(BigDecimal.class, numberFormat, true));
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("dd/MM/yyyy"), true));
}
});
}
public ModelAndView(HttpServletRequest request, HttpServletResponse response) throws Exception {
return new ModelAndView()
.addAllObjects(
createBinder(request, new Command())
.getBindingResult().getModel())
.addObject(accountRepository.findById(Integer.valueOf(request.getParameter("accountId"))));
}
}
Inside your JSP
<c:if test="{not empty account}">
<!--If you need a BigDecimal PropertyEditor-->
<spring:bind path="command.bigDecimal">
<spring:transform value="${account.balance}"/>
</spring:bind>
<!--If you need a Date PropertyEditor-->
<spring:bind path="command.date">
<spring:transform value="${account.joinedDate}"/>
</spring:bind>
</c:if>
It is useful when your Target command does not provide a PropertyEditor which needs to be used in another command.

Related

Liferay 7.3 how to get the parameter values inside a portlet and access in view.jsp

I am trying to get the parameters inside a portlet in Liferay 7.3. If I pass the parameter like:
http://localhost:8080/web/guest?name=abhi
in a web page, that contains my portlet. So My question is
Q1) can I get this parameter inside the Portlet Controller (doView method) when user reloads the above page, by doing something like:
import com.liferay.portal.kernel.util.ParamUtil;
public class MySamplePortlet extends MVCPortlet {
#Override
public void doView(RenderRequest renderRequest, RenderResponse renderResponse)
throws IOException, PortletException {
String name = ParamUtil.getString(renderRequest, "name");
System.out.println(name);
}
}
Here I am getting a blank for the 'name' when printing.
And
Q2) how I check the condition of this parameter in view.jsp view file (how to get the class variable value inside the view file) ?
<% if(name) %>
render form view
<% else %>
render messageBox view
......
I want to render different views according to the parameter value.
Parameters to a portlet are typically namespaced - e.g. a HTTP-parameter name could be anything to any portlet - and a page potentially has many portlets. All of them might think of name as something different: A city, a user, a customer, the currently used computer, a pet...
Thus any form typically submits values that look like (in jsp-lingo):
<input name="<portlet:namespace/>name" ..../> rather than <input name="name" ..../>
If you use tags that are portlet-aware, they might do the decoration automagically, e.g. <aui:input name="name" .../>.
Utilizing undirected and unnamespaced parameters in the portlet world might generate maintenance nightmares, specifically when you run into your first ambiguous name.
However, you can deactivate the namespacing, per portlet. Or you can manually access the underlying HTTPServletRequest. Both are strongly discouraged. Here's how you shoot yourself in the foot if you like to:
Set the portlet's property com.liferay.portlet.requires-namespaced-parameters=false
Utilize PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(renderRequest)) (what these functions do - and why you need them both - is described, for example, here)
So the ParamUtil will work if the parameter is for the portlet. in this case it seems you want the parameter in the url in general meaning not specific for the portlet. to achieve this you need to use PortalUtil
HttpServletRequest httpReq = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(req));
String name = httpReq.getParameter("name");
Note im looking for the original request. not the portlet request.
hope it helps

Bind list or array to form in Thymleaf

On my website I have a few checkboxes each of them contains id in value attribute. After submitting form I'd like to have a list containing ids of checked checkboxes to be passed to the controller. That's how I want to make new page comparing n products.
Controller can accept List<Long> or long[]. That's what I have for now:
HTML:
<form th:action="#{/comparison}" th:object="${productsComparison}" target="_blank" method="post">
<table>
<tr data-th-each="item, iter : ${items.item}">
<td>
<input type="checkbox" th:name="|productsComparison.ids[${iter.index}]|" th:value="${item.id}"/>
</td>
</tr>
</table>
I've added to my controller List<Long> wrapped in ProductComparison with appropriate getters and setters. After submitting form list is always null.
Controller:
#RequestMapping("/productsPage")
public String showProducts(Model model) {
ProductsComparison productsComparison = new ProductsComparison();
model.addAttribute("productsComparison", productsComparison);
}
#RequestMapping("/comparison")
public String compareProducts(#ModelAttribute ProductsComparison productsComparison) {
System.out.println("List: " + productComparison.getIds());
// Always shows null
return "comparison";
}
public class ProductsComparison {
private List<Long> ids;
// Getters & setters
}
The underscores __ are ThymeLeaf's syntax for a preprocessing expression. Or in layman's terms, the stuff inside of the underscores are processed before the rest of the expression.
This is important because your expression is using an array, and the ${iter.index} portion of it gives the array index.
If you are curious or if anyone else stumbles upon this. th:name is no different than the html attribute name. The ThymeLeaf engine will just shove a name attribute into the html entity or overwrite the old one. ThymeLeaf has a ton of properties like this. th:field is a totally different beast though. It is what tells ThymeLeaf to bind the input of your form to the back forming bean or your model attribute, th:object="${productsComparison}". So with the expression th:field="*{ids[__${iter.index}__]}", Thymeleaf is going to call productsComparison.getIds[0] and the corresponding setter.
Note about th:name if you are submitting with Javascript of any kind, you probably want to use this. Most likely you are serializing your form, and the JSON created by this method call will use the name property.
If you want to know more about ThymeLeaf preprocessing expressions, there is a bit in the documentation about it.
I've finally found solution. Instead of th:name I had to use th:field.
th:field="*{ids[__${iter.index}__]}"
Because it's field I didn't have to specify object productsComparison before ids. ids field is List<String>.
To be honest I have no idea what underscores do, I will be glad if someone could explain.

Java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'loginBean' available as request attribute [duplicate]

This is meant to be an extensive canonical question & answer post for these types of questions.
I'm trying to write a Spring MVC web application where users can add movie names to an in-memory collection. It's configured like so
public class Application extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] {};
}
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { SpringServletConfig.class };
}
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
and
#Configuration
#ComponentScan("com.example")
public class SpringServletConfig extends WebMvcConfigurationSupport {
#Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver vr = new InternalResourceViewResolver();
vr.setPrefix("WEB-INF/jsps/");
vr.setSuffix(".jsp");
return vr;
}
}
There's a single #Controller class in the com.example package
#Controller
public class MovieController {
private final CopyOnWriteArrayList<Movie> movies = new CopyOnWriteArrayList<>();
#RequestMapping(path = "/movies", method = RequestMethod.GET)
public String homePage(Model model) {
model.addAttribute("movies", movies);
return "index";
}
#RequestMapping(path = "/movies", method = RequestMethod.POST)
public String upload(#ModelAttribute("movie") Movie movie, BindingResult errors) {
if (!errors.hasErrors()) {
movies.add(movie);
}
return "redirect:/movies";
}
public static class Movie {
private String filmName;
public String getFilmName() {
return filmName;
}
public void setFilmName(String filmName) {
this.filmName = filmName;
}
}
}
WEB-INF/jsps/index.jsp contains
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Movies</title>
</head>
<body>
Current Movies:
<c:forEach items="${movies}" var="movieItem">
<ul>
<li>${movieItem.filmName}</li>
</ul>
</c:forEach>
<form:form>
<div>Movie name:</div>
<form:input path="filmName" type="text" id="name" />
<input type="submit" value="Upload">
</form:form>
</body>
</html>
The application is configured with context path /Example. When I send a GET request to
http://localhost:8080/Example/movies
the request fails, Spring MVC responds with a 500 status code, and reports the following exception and stack trace
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute
org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:144)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.java:168)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getPropertyPath(AbstractDataBoundFormElementTag.java:188)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getName(AbstractDataBoundFormElementTag.java:154)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.writeDefaultAttributes(AbstractDataBoundFormElementTag.java:117)
org.springframework.web.servlet.tags.form.AbstractHtmlElementTag.writeDefaultAttributes(AbstractHtmlElementTag.java:422)
org.springframework.web.servlet.tags.form.InputTag.writeTagContent(InputTag.java:142)
org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal(AbstractFormTag.java:84)
org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:80)
org.apache.jsp.WEB_002dINF.jsps.index_jsp._jspx_meth_form_005finput_005f0(index_jsp.java:267)
org.apache.jsp.WEB_002dINF.jsps.index_jsp._jspx_meth_form_005fform_005f0(index_jsp.java:227)
org.apache.jsp.WEB_002dINF.jsps.index_jsp._jspService(index_jsp.java:142)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:438)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:396)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:340)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:168)
org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303)
org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1257)
org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1037)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:980)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
I expected the JSP to generate an HTML <form> with a single text input, for a Movie name, and a submit button, that I can use to send a POST request with a new Movie. Why does the JSP servlet instead fail to render Spring's <form:form> tag?
You're trying to use Spring MVC's form tag.
This tag renders an HTML form tag and exposes a binding path to
inner tags for binding. It puts the command object in the PageContext
so that the command object can be accessed by inner tags. [..]
Let’s assume we have a domain object called User. It is a JavaBean
with properties such as firstName and lastName. We will use it as the
form backing object of our form controller which returns form.jsp.
In other words, Spring MVC will extract a command object and use its type as a blueprint for binding path expressions for form's inner tags, like input or checkbox, to render an HTML form element.
This command object is also called a model attribute and its name is specified in the form tag's modelAttribute or commandName attributes. You've omitted it in your JSP
<form:form>
You could've specified a name explicitly. Both of these are equivalent.
<form:form modelAttribute="some-example-name">
<form:form commandName="some-example-name">
NOTE: Spring 5 has removed the commandName attribute, see the upgrade notes, here.
The default attribute name is command (what you see in error message). A model attribute is an object, typically a POJO or collection of POJOs, that your application supplies to the Spring MVC stack and which the Spring MVC stack exposes to your view (ie. the M to the V in MVC).
Spring MVC collects all model attributes in a ModelMap (they all have names) and, in the case of JSPs, transfers them to the HttpServletRequest attributes, where JSP tags and EL expressions have access to them.
In your example, your #Controller handler method which handles a GET to the path /movies adds a single model attribute
model.addAttribute("movies", movies); // not named 'command'
and then forwards to the index.jsp. This JSP then tries to render
<form:form>
...
<form:input path="name" type="text" id="name" />
...
</form:form>
While rendering this, FormTag (in reality, the InputTag) tries to find a model attribute named command (the default attribute name) so that it can produce an HTML <input> element with a name attribute constructed from the path expression and the corresponding property value, ie. the result of Movie#getFilmName().
Since it cannot find it, it throws the exception you see
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute
The JSP engine catches it and responds with a 500 status code. If you want to take advantage of a Movie POJO to simply construct your form correctly, you can add a model attribute explicitly with
model.addAttribute("movie", new Movie());
or have Spring MVC create and add one for you (must have an accessible parameterless constructor)
#RequestMapping(path = "/movies", method = RequestMethod.GET)
public String homePage(#ModelAttribute("command") Movie movie, Model model) {...}
Alternatively, include a #ModelAttribute annotated method in your #Controller class
#ModelAttribute("command")
public Movie defaultInstance() {
Movie movie = new Movie();
movie.setFilmName("Rocky II");
return movie;
}
Note that Spring MVC will call this method and implicitly add the object returned to its model attributes for each request handled by the enclosing #Controller.
You may have guessed from this description that Spring's form tag is more suited for rendering an HTML <form> from an existing object, with actual values. If you want to simply create a blank <form>, it may be more appropriate to construct it yourself and not rely on any model attributes.
<form method="post" action="${pageContext.request.contextPath}/movies">
<input name="filmName" type="text" />
<input type="submit" value="Upload" />
</form>
On the receiving side, your POST handler method, will still be able to extract the filmName input value and use it to initialize a Movie object.
Common Errors
As we've seen, FormTag looks for a model attribute named command by default or with the name specified in either modelAttribute or commandName. Make sure you're using the right name.
ModelMap has a addAttribute(Object) method which adds
the supplied attribute to this Map using a generated name.
where the general convention is to
return the uncapitalized short name of the [attribute's] Class, according to
JavaBeans property naming rules: So, com.myapp.Product becomes
product; com.myapp.MyProduct becomes myProduct; com.myapp.UKProduct
becomes UKProduct
If you're using this (or a similar) method or if you're using one of the #RequestMapping supported return types that represents a model attribute, make sure the generated name is what you expect.
Another common error is to bypass your #Controller method altogether. A typical Spring MVC application follows this pattern:
Send HTTP GET request
DispatcherServlet selects #RequestMapping method to handle request
Handler method generates some model attributes and returns view name
DispatcherServlet adds model attributes to HttpServletRequest and forwards request to JSP corresponding to view name
JSP renders response
If, by some misconfiguration, you skip the #RequestMapping method altogether, the attributes will not have been added. This can happen
if your HTTP request URI accesses your JSP resources directly, eg. because they are accessible, ie. outside WEB-INF, or
if the welcome-list of your web.xml contains your JSP resource, the Servlet container will render it directly, bypassing the Spring MVC stack entirely
One way or another, you want your #Controller to be invoked so that the model attributes are added appropriately.
What does BindingResult have to do with this?
A BindingResult is a container for initialization or validation of model attributes. The Spring MVC documentation states
The Errors or BindingResult parameters have to follow the model object
that is being bound immediately as the method signature might have
more than one model object and Spring will create a separate
BindingResult instance for each of them [...]
In other words, if you want to use BindingResult, it has to follow the corresponding model attribute parameter in a #RequestMapping method
#RequestMapping(path = "/movies", method = RequestMethod.POST)
public String upload(#ModelAttribute("movie") Movie movie, BindingResult errors) {
BindingResult objects are also considered model attributes. Spring MVC uses a simple naming convention to manage them, making it easy to find a corresponding regular model attribute. Since the BindingResult contains more data about the model attribute (eg. validation errors), the FormTag attempts to bind to it first. However, since they go hand in hand, it's unlikely one will exist without the other.
I tried to migrate my application to Spring5 and noticed the same issue. It was caused by the moment that the 'commandName' attribute is not supported anymore and I had to use 'modelAttribute' instead.
To make things simple with the form tag just add a "commandName" which is a horrible name for what it is actually looking for...it wants the object you named in the MdelAttribute annotation. So in this case commandName="movie".
That'll save you reading long winded explanations friend.
I had this error on a screen with multiple forms that do a search. Each form posts to its own controller method with results shown on same screen.
Problem: I missed adding the other two forms as model attributes in each controller method causing that error when screen renders with results.
Form1 -> bound to Bean1 (bean1) -> Posting to /action1
Form2 -> bound to Bean2 (bean2) -> Posting to /action2
Form3 -> bound to Bean3 (bean2) -> Posting to /action3
#PostMapping
public String blah(#ModelAttribute("bean1") Bean1 bean, Model model){
// do something with bean object
// do not miss adding other 2 beans as model attributes like below.
model.addAttribute("bean2", new Bean2());
model.addAttribute("bean3", new Bean3());
return "screen";
}
#PostMapping
public String blahBlah(#ModelAttribute("bean2") Bean2 bean, Model model){
// do something with bean object
// do not miss adding other 2 beans as model attributes like below.
model.addAttribute("bean1", new Bean1());
model.addAttribute("bean3", new Bean3());
return "screen";
}
#PostMapping
public String blahBlahBlah(#ModelAttribute("bean3") Bean3 bean, Model model){
// do something with bean object
// do not miss adding other 2 beans as model attributes like below.
model.addAttribute("bean1", new Bean1());
model.addAttribute("bean2", new Bean2());
return "screen";
}
In my case, it worked by adding modelAttribute="movie" to the form tag, and prepending the model name to the attribute, something like <form:input path="filmName" type="text" id="movie.name" />
Updating from Spring version 3 to Spring version 5, produces the same error. All answers were satisfied already in my code. Adding the annotation #ControllerAdvice solved the problem for me.
If your Model object is correctly being passed to the GET API call but still have this error, you may look at the html or jsp page also to check whether correct variables names are provided and tags are used correctly. In my case, I forgot to include the objects under the closing <form> tag.

How to bind an object inside the list collection of the command object in Spring MVC

My command object have a list of objects. I want to bind a text field to the attribute of the object inside that list. Is it possible to do in Spring MVC?
Command object class
public class SubDevisonDto {
private String devId;
private List subDevisions;
Subdevision object class mentioned in the list
public class SubDivison implements Serializable{
private String subDivisonName;
private String createdBy;
private String createdDate;
private String developerID;
private List users;
I want text box to set the value for subDivisonName field.
I have written the Spring MVC tags like this.
<spring:bind path="subdivisondto.subDevisions[0].subDivisonName">
<span class="formw">
<input name="subDivisonName" type="text" style="width:350px;" />
</span>
</spring:bind>
Just for test purpose I have given it as 0. If it's working I can make it to a variable. my requirement is, I should let the user to dynamically add subdevision objects. So, initially when page is loading I will just show one text box. I will give a button for him to add if he want to add more. I will dynamically generate text boxes when he clicks the add button. After that I have to submit the form with the list.
This jsp code gives me an error. It says:
org.springframework.beans.NullValueInNestedPathException
Is there anyway for me to do this in jsp code?
I found the answer for my question. But, it's not the solution for my requirement as I need to implement a dynamic list. but I found a solution for this question.
As I understood, first time we have to send data from back end to bind input elements. I didn't find a way to bind form elements which takes input without sending a list data from beck end. But when we send data and bind the elements, we can take input from those elements. So, I think to bind the element in a situation like this we need to send data first time. Correct me if this statement is wrong. Because, that would be a more good solution for me.
We need to use the lazy list and jsp code is bit modified.
Your command class object should be created as below mentioned.
import org.apache.commons.collections.list.LazyList;
import org.apache.commons.collections.FactoryUtils;
public class SubDevisonDto {
private String devId;
private List subDevisions =
LazyList.decorate(
new ArrayList(),
FactoryUtils.instantiateFactory(SubDivison.class));
JSP code should look like below.
<c:forEach items="${subs.subDevisions}" var="obj" varStatus="gridRow">
Binding an input element text box
<spring:bind path="subdivisondto.subDevisions[${gridRow.index}].subDivisonName">
<span class="formw"><input name="<c:out value="${status.expression}"/>" type="text" style="width:350px;" />
binding an input element check box. This input element makes a list.
<spring:bind path="subs.subDevisions[${gridRow.index}].users">
<c:forEach items="${obj.users}" var="dependenttwo" varStatus="dependentRowtwo">
<li>
<input name="<c:out value="${status.expression}"/>" type="checkbox" class="users" value="<c:out value="${dependenttwo}"/>"/>
<c:out value="${dependenttwo}"/>
</li>
</c:forEach>
</spring:bind>
`subs` is a map key name. the value for this key `subs` is a list of my DTO objects which named as `SubDevisonDto `
This code works fine for me.
Thanks the support given.
In dto :
private List<SubDivision> SubDivisions = new AutoPopulatingList<SubDivision>(new SubDivisionFactory());
and factory would be something like:
public class SubDivisionFactory implements AutoPopulatingList.ElementFactory<SubDivision> {
public String createElement(int index) {
SubDivision subDivision = new SubDivision();
return subDivision;
}
}
using AutopopulatingList from spring. And your jsp will look the same, you can iterate over as many as you want.

Refer to html elements by class in spring mvc controller

I know how to refer to HTML elements by name with request.getParameter("foo");
But I have various groups of elements within a form that each have a seperate 'class' attribute. Is there any way to refer to these by their class names?
My controller is in the form below:
#Controller
#MultipartConfig()
public class FooController {
//get parameters
return "view";
}
My HTML input elements are in the form below:
<input class="bar" type="checkbox" name="elementName" />
Basically I want to say in my controller, "give me all the elements of class 'bar'". Is it possible?
No, a Controller doesn't actually know about the contents of the view.
Parameters such as
request.getParameter("foo")
comes from the HTTP request and not from reading the HTML page. The "foo" part comes from the "name" attribute of the form element when the form is submitted.
Instead, you could use some JavaScript to get a list of elements that match particular CSS classes and then dynamically edit your form submit to GET/POST the contents of these elements to your controller.
No it is not possible, because when the user POSTs data to your webapp, the HTML element classnames are not sent - only the name and values of the input elements.
As per the above, no. But: if you use Spring Forms with its taglib and a backing form class, Spring will automagically bind the form elements to the form class members. Your handler method then changes to:
#Controller
public class MyController {
#RequestMapping("/foo/somevalue.do")
public String FooController (
#ModelAttribute("myForm") MyFormBean formBean
){
return "view"; // name of the JSP
}
}
The form bean:
class MyFormBean
private String elementName
//getters and setters
Your JSP:
<form:input path="elementName" />

Categories

Resources