diff --git a/core/src/main/java/org/apache/struts2/components/CheckboxList.java b/core/src/main/java/org/apache/struts2/components/CheckboxList.java index e83091888..601ce5bdf 100644 --- a/core/src/main/java/org/apache/struts2/components/CheckboxList.java +++ b/core/src/main/java/org/apache/struts2/components/CheckboxList.java @@ -48,7 +48,7 @@ import com.opensymphony.xwork2.util.ValueStack; allowDynamicAttributes = true) public class CheckboxList extends ListUIBean { final public static String TEMPLATE = "checkboxlist"; - + public CheckboxList(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { super(stack, request, response); } @@ -56,9 +56,19 @@ public class CheckboxList extends ListUIBean { protected String getDefaultTemplate() { return TEMPLATE; } - + public void evaluateExtraParams() { super.evaluateExtraParams(); } -} \ No newline at end of file + /** + * Checkboxlist tag requires lazy evaluation as list of tags is dynamically generated using + * + * @return boolean true by default + */ + @Override + protected boolean lazyEvaluation() { + return true; + } + +} diff --git a/core/src/main/java/org/apache/struts2/components/ListUIBean.java b/core/src/main/java/org/apache/struts2/components/ListUIBean.java index 26484f250..bfaffe6f1 100644 --- a/core/src/main/java/org/apache/struts2/components/ListUIBean.java +++ b/core/src/main/java/org/apache/struts2/components/ListUIBean.java @@ -195,7 +195,6 @@ public abstract class ListUIBean extends UIBean { this.listTitle = listTitle; } - public void setThrowExceptionOnNullValueAttribute(boolean throwExceptionOnNullValueAttribute) { this.throwExceptionOnNullValueAttribute = throwExceptionOnNullValueAttribute; } diff --git a/core/src/main/java/org/apache/struts2/components/Radio.java b/core/src/main/java/org/apache/struts2/components/Radio.java index 0315cb65b..ba5eb471f 100644 --- a/core/src/main/java/org/apache/struts2/components/Radio.java +++ b/core/src/main/java/org/apache/struts2/components/Radio.java @@ -57,7 +57,7 @@ import javax.servlet.http.HttpServletResponse; allowDynamicAttributes = true) public class Radio extends ListUIBean { final public static String TEMPLATE = "radiomap"; - + public Radio(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { super(stack, request, response); } @@ -65,8 +65,19 @@ public class Radio extends ListUIBean { protected String getDefaultTemplate() { return TEMPLATE; } - + public void evaluateExtraParams() { super.evaluateExtraParams(); } -} \ No newline at end of file + + /** + * Radio tag requires lazy evaluation as list of tags is dynamically generated using + * + * @return boolean true by default + */ + @Override + protected boolean lazyEvaluation() { + return true; + } + +} diff --git a/core/src/main/java/org/apache/struts2/components/UIBean.java b/core/src/main/java/org/apache/struts2/components/UIBean.java index 9ec23d5c7..a9b8f50f9 100644 --- a/core/src/main/java/org/apache/struts2/components/UIBean.java +++ b/core/src/main/java/org/apache/struts2/components/UIBean.java @@ -1277,8 +1277,8 @@ public abstract class UIBean extends Component { String attrValue = entry.getValue(); if (!isValidTagAttribute(attrName)) { - if (ComponentUtils.altSyntax(getStack()) && ComponentUtils.isExpression(attrValue)) { - dynamicAttributes.put(attrName, String.valueOf(ObjectUtils.defaultIfNull(findString(attrValue), attrValue))); + if (ComponentUtils.altSyntax(getStack()) && ComponentUtils.containsExpression(attrValue) && !lazyEvaluation()) { + dynamicAttributes.put(attrName, ObjectUtils.defaultIfNull(findString(attrValue), attrValue)); } else { dynamicAttributes.put(attrName, attrValue); } @@ -1302,4 +1302,14 @@ public abstract class UIBean extends Component { } } + /** + * Used to avoid evaluating attributes in {@link #evaluateParams()} or {@link #evaluateExtraParams()} + * as evaluation will happen in tag's template + * + * @return boolean false if evaluation should be performed in ftl + */ + protected boolean lazyEvaluation() { + return false; + } + } diff --git a/core/src/main/resources/template/simple/checkboxlist.ftl b/core/src/main/resources/template/simple/checkboxlist.ftl index 3fa27f189..87bef6651 100644 --- a/core/src/main/resources/template/simple/checkboxlist.ftl +++ b/core/src/main/resources/template/simple/checkboxlist.ftl @@ -30,7 +30,7 @@ <#assign itemKeyStr = stack.findString('top')> <#if parameters.listLabelKey??> - <#-- checks the valueStack for the 'valueKey.' The valueKey is then looked-up in the locale + <#-- checks the valueStack for the 'valueKey.' The valueKey is then looked-up in the locale file for it's localized value. This is then used as a label --> <#assign itemValue = struts.getText(stack.findString(parameters.listLabelKey))/> <#elseif parameters.listValue??> @@ -95,9 +95,10 @@ <#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" /> <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" /> <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" /> + <#global evaluate_dynamic_attributes = true/> <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" /> /> - + <#if parameters.id?has_content> for="${parameters.id}-${itemCount}"<#rt/> <#else> @@ -106,11 +107,10 @@ class="checkboxLabel">${itemValue} <#else> -   <#if parameters.disabled!false> disabled="disabled"<#rt/> - /> \ No newline at end of file + /> diff --git a/core/src/main/resources/template/simple/dynamic-attributes.ftl b/core/src/main/resources/template/simple/dynamic-attributes.ftl index 47a91139f..7f15aa48f 100644 --- a/core/src/main/resources/template/simple/dynamic-attributes.ftl +++ b/core/src/main/resources/template/simple/dynamic-attributes.ftl @@ -30,7 +30,11 @@ <#list aKeys?filter(acceptKey) as aKey><#rt/> <#assign keyValue = parameters.dynamicAttributes.get(aKey)/> <#if keyValue?is_string> - <#assign value = struts.translateVariables(keyValue)!keyValue/> + <#if evaluate_dynamic_attributes!false == true> + <#assign value = struts.translateVariables(keyValue)!keyValue/><#rt/> + <#else> + <#assign value = keyValue/><#rt/> + <#else> <#assign value = keyValue?string/> diff --git a/core/src/main/resources/template/simple/radiomap.ftl b/core/src/main/resources/template/simple/radiomap.ftl index 5c37a4b4b..597300e95 100644 --- a/core/src/main/resources/template/simple/radiomap.ftl +++ b/core/src/main/resources/template/simple/radiomap.ftl @@ -27,7 +27,7 @@ <#assign itemKeyStr = stack.findString('top')> <#if parameters.listValueKey??> - <#-- checks the valueStack for the 'valueKey.' The valueKey is then looked-up in the locale + <#-- checks the valueStack for the 'valueKey.' The valueKey is then looked-up in the locale file for it's localized value. This is then used as a label --> <#assign valueKey = stack.findString(parameters.listValueKey)!''/> <#if valueKey?has_content> @@ -94,9 +94,10 @@ <#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" /> <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" /> <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" /> +<#global evaluate_dynamic_attributes = true/> <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" /> /><#rt/> - \ No newline at end of file +