I'm working on a JSP tag. Here is the old line that starts looping through items in a model:
<c:forEach var="toc" items="${requestScope[formKey].model.sharingTocs}">
But the code has been refactored so the model path (model.sharingTocs
above) is now dynamic rather than fixed. It is now passed into the tag via a JSP @attribute
:
<%@attribute name="path" required="true"%>
So ${path}
now evaluates to "model.sharingTocs"
.
How can items
now be assigned?
Well. Good question.
This is a solution: writing a custom jstl tag to Evaluate a property expression of a bean:
<mytag:eval bean="${requestScope['formKey']}" propertyExpression = "${path}" var="items" />
And ForEach:
<c:forEach var="toc" items="${items}">
</c:forEach>
Sample code of mytag:eval JSTL tag ( Classic model )
public class EvalTag extends TagSupport
{
private Object bean;
private String propertyExpression; //Ex: 'model.sharingTocs'
private String var;
//............
@Override
public int doEndTag() throws JspException {
try {
// Use reflection to eval propertyExpression ('model.sharingTocs') on the given bean
Object propObject = SomeLibs.eval ( this.bean, this.propertyExpression);
this.pageContext.getRequest().setAttribute(this.var, propObject);
// You can add propObject into Other scopes too.
} catch (Exception ex) {
throw new JspTagException(ex.getMessage(), ex);
}
return EVAL_PAGE;
}
//............
// SETTERS here
}
A lib you can use to eval propertyExpression of a bean is Apache bean utils.
http://commons.apache.org/proper/commons-beanutils/apidocs/org/apache/commons/beanutils/package-summary.html#standard.nested
If you are using spring you can utilise the spring tag library, it also assumes you are inside a form:form tag.
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ attribute name="path" required="false" %>
<spring:bind path="${path}">
<c:forEach var="item" items="${status.value}">
${item}
</c:forEach>
</spring:bind>
It's been quite a while since I asked this question but (with new knowledge gained since) I think this ought to work:
<c:set var="itemsPath" value="requestScope[formKey].${path}"/>
<c:forEach var="toc" items="${itemsPath}">
i.e. set up an intermediary JSTL variable with the full path to the items and evaluate that one instead.