I'm trying to do something that seems like it should be relatively straightforward and running into a bit of a wall.
Let's say I've got a list of products which I expose as a request attribute under the name products. Let's also say that each product has an id field, and that I also have a bunch of request attributes set in the form of selectedProduct_<product-id> to indicate which ones are selected.
I understand there are better ways to represent this information, such as placing all the selected ids into a Map and checking against that, but let's assume that I don't have access to that approach for whatever reason.
So what I'd like to do is iterate products and emit some markup only if there is a selectedProduct_... attribute set for the current product. Something like:
<c:forEach var="product" items="${products}">
<c:if test="${! empty selectedProduct_${product.id}}">
<div class="productId">${product.id}</div>
</c:if>
</c:forEach>
But of course that doesn't work, as it dies on ${! empty selectedProduct_${product.id}}.
What will work is if I hardcode the product-id into the expression, like:
${! empty selectedProduct_17}
...assuming that '17' is a valid product id. Obviously that's not practical, but hopefully it illustrates what I'm trying to accomplish. Basically I need to:
Determine the correct selectedProduct_... value to use for each iteration in the forEach loop. Something as simple as <c:set var="key" value="selectedProduct_${product.id}"/> would do this, except I'm not sure how to then take key and use it to get the value of the request attribute with that name (without cheating and running literal Java code inside a <% %> block).
Get the value of the request attribute whose name I determined in #1. This seems to be the tricky part.
Is this possible using pure JSP/JSTL? I know I could run some Java code inside of <% %> to solve this, but that seems like it would be in exceedingly bad form. Surely a more elegant solution exists?
You can by using implicit objects:
There are objects that allow access to the various scoped variables described in Using Scope Objects.
pageScope: Maps page-scoped variable names to their values
requestScope: Maps request-scoped variable names to their values
sessionScope: Maps session-scoped variable names to their values
applicationScope: Maps application-scoped variable names to their values
When an expression references one of these objects by name, the appropriate object is returned instead of the corresponding attribute. For example, ${pageContext} returns the PageContext object, even if there is an existing pageContext attribute containing some other value.
So, for example:
<c:set var="selectedProductAttrName" value="selectedProduct_${product.id}"/>
${requestScope[selectedProductAttrName]}
Related
I have a JSP attribute named "form" set followingly
<c:set value="${fieldAttributeMap[rowId].buildForm}" var="form" />
This works. The attribute "form" contains a Java object, which will used for further evaluation and displaying later in the JSP. However, I would like to use it in a more general way without knowing what the form name is beforehand - it could be named e.g. "modelForm" instead of "buildForm". If we assume that I have stored the name of the variable in JSP attribute "formName"
<c:set value="buildForm" var="formName" />
how can I use this to set the JSP attribute "form" like in the first code example? Basically the expression would have to be evaluated twice, like in this imaginary, non-working example:
<c:set value="${fieldAttributeMap[rowId][${formName}]}" var="form" />
Only workarounds which come to my mind are either writing my own tag or using the antiquated Struts bean:define tag. But I'm hoping there is some better solution or workaround.
Edit: there was a suggestion that this question may be a duplicate of calling another variable using a variable value as parameter in jstl However, the solution offered there is not applicable here, as I need to substitute the name of the attribute as a property of another Java object.
You simply need ${fieldAttributeMap[rowId][formName]}
I was explaining to a colleague the way of getting list data from a JSP page to back to the action class by using indices as explained here and here. He didn't quite understand and fumbled a bit on his own until he suddenly he made it work by not using indices at all!
In his JSP page he had:
<input type="checkbox" name="contactNameList" value="someValue1">
<input type="checkbox" name="contactNameList" value="someValue2">
<input type="checkbox" name="contactNameList" value="someValue3">
<input type="checkbox" name="contactNameList" value="someValue4">
In his action class he had the 'appropiate' setters:
public List<String> getContactNameList()
public void setContactNameList(List<String> list)
I'm baffled as to why this work. I think this works because he is sending non-bean data (in this case strings) and there is an intelligence build into Struts2/OGNL to append values to lists rather than overwrite them.
Can anybody explain with great detail what is going behind the hood in this "no indices" case? How is the list of strings instantiated and populated with the snippets above?
You should understand that bean data and not bean data are passed as parameters to the action. The parameters has a structure that you can find if you implement ParameterAware.
Note that all parameter values for a given name will be returned, so
the type of the objects in the map is java.lang.String[].
Then XWork Type Conversion make its best to convert this map to beans properties. See Built in Type Conversion Support.
Routine type conversion in the framework is transparent. Generally,
all you need to do is ensure that HTML inputs have names that can be
used in OGNL expressions. (HTML inputs are form elements and other
GET/POST parameters.)
In the no indexes case parameters are mapped under the one key, rather than indexed names are used under their own names.
You have to set index value in above code
like
<input type="checkbox" name="contactNameList[0]" value="someValue1">
I am using EL to pull an object from a bean stored in the session.
The object is question is called P_COV_MOULT and is declared as follows:
this.P_COV_MOULT = new FormField("F_B_P_COV_MOULT","");
And is accessed via a getter method like so:
public FormField getP_COV_MOULT() {
return P_COV_MOULT;
}
Which was generated by NetBeans.
I appreciate that the usage of all caps separated by underscores does not fit the naming conventions for non constants, but it's useful for semantic value.
I have many other properties stored in this same bean, and am pulling those all fine and have been for a while.
However, with this P_COV_MOULT and other properties that are in the format of
multiple underscore separated values but with the first one being a single character, I get a javax.el.PropertyNotFoundException.
The objects/properties are stored in exactly the same way as all the rest, but they just can't be found.
I've tried inserting a separate method getp_COV_MOULT(), on the assumtion that it was converting the name in EL to a getter incorrectly (or correctly) and not calling getP_COV_MOULT(), but instead calling a different method, such as getp_COV_MOULT(), but that didn't work.
Here is the EL:
<input type="text" name="${findingBiometrics.P_COV_MOULT.name}" id="${findingBiometrics.P_COV_MOULT.name}" value="${findingBiometrics.P_COV_MOULT.value}"
${findingBiometrics.P_COV_MOULT.readonlyState} ${findingBiometrics.P_COV_MOULT.disabledState} size="5" />
Any ideas would be very much appreciated. Thanks.
The convention is that property names start with a small letter. So if the property name is theProperty, then the getter is named getTheProperty. So if you have a getter called getP_COV_MOULT, I would expect the EL property to be p_COV_MOULT. However, your naming is pretty weird, so I'm not 100% sure it would work.
When I provide a dynamic name of checkbox inside a for loop like
<input type="checkbox" name="<%=i%>" />
How can I retrieve the value in servlet?
Three ways:
Just rerun the same for loop in servlet as you did in JSP (you truly know the loop conditions) and do request.getParameter(i) on every iteration and if necessary add every parameter value to a List<String> so that you can easily process it afterwards.
Prefix the parameter name with a certain string, e.g. name="foo${i}", grab all parameters by request.getParameterMap(), loop over it and determine if the name.startsWith("foo") and if necessary collect the matched values in a List<String>.
Just give all checkboxes the same name, but a different value and grab the checked ones by request.getParameterValues("checkboxname");. It will return a String[] with all values.
Way 3 is the normal practice by the way.
That said, scriptlets (those <% %> things in your code) indicates bad practices. I'd suggest to throw away the old fashioned JSP/Servlet books/tutorials you're currently reading and get yourself through the following links to learn how to do things properly:
Beginning and intermediate JSP/Servlet tutorials
JSP/Servlet best practices
How to avoid Java code in JSP
I have a hidden field:
<input type="hidden" name="champs" id="champs">
I want do a <logic:equal> with the content of this field hidden, I tried the solutions but not work
<logic:equal name="virement" property="statut" value='champs' >
just be there is a syntax very precise in the value property of the logic: equal that I can found.
I'm a little rusty with this, but here are some hints:
Your field "champs" is a browser field, not a Java variable. When your request arrives at your servlet, the contents of browser fields have been transferred to request parameters. So the value in your field will end up in a predefined object called request, and for convenience broken down some more in a bean called param. There's a syntax for accessing this stuff... see below.
A little more detail (though I've seen it explained better) can be found in this page and maybe this one. Better yet, here
You can Google for "JSP Expression Language" to get more information.
You can use the struts tag html:hidden instead of input type = "hidden"