SPR-5931 - Allow non-standard attributes in <form> tags
This commit is contained in:
parent
566eeba8ca
commit
982ece595c
|
|
@ -16,8 +16,13 @@
|
|||
|
||||
package org.springframework.web.servlet.tags.form;
|
||||
|
||||
import javax.servlet.jsp.JspException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.tagext.DynamicAttributes;
|
||||
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
|
@ -26,10 +31,16 @@ import org.springframework.util.StringUtils;
|
|||
* a set of properties corresponding to the set of HTML attributes that are common
|
||||
* across elements.
|
||||
*
|
||||
* <p>Additionally, this base class allows for rendering non-standard attributes
|
||||
* as part of the tag's output. These attributes are accessible to subclasses if
|
||||
* needed via the {@link AbstractHtmlElementTag#getDynamicAttributes() dynamicAttributes}
|
||||
* map.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Jeremy Grelle
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElementTag {
|
||||
public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElementTag implements DynamicAttributes{
|
||||
|
||||
public static final String CLASS_ATTRIBUTE = "class";
|
||||
|
||||
|
|
@ -98,6 +109,8 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
|
||||
private String onkeydown;
|
||||
|
||||
private Map<String, Object> dynamicAttributes;
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of the '<code>class</code>' attribute.
|
||||
|
|
@ -370,6 +383,22 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
return this.onkeydown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the map of dynamic attributes.
|
||||
*/
|
||||
protected Map<String, Object> getDynamicAttributes() {
|
||||
return this.dynamicAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void setDynamicAttribute(String uri, String localName, Object value ) throws JspException {
|
||||
if (this.dynamicAttributes == null) {
|
||||
this.dynamicAttributes = new HashMap<String, Object>();
|
||||
}
|
||||
dynamicAttributes.put(localName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the default attributes configured via this base class to the supplied {@link TagWriter}.
|
||||
|
|
@ -383,6 +412,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
|
||||
/**
|
||||
* Writes the optional attributes configured via this base class to the supplied {@link TagWriter}.
|
||||
* The set of optional attributes that will be rendered includes any non-standard dynamic attributes.
|
||||
* Called by {@link #writeDefaultAttributes(TagWriter)}.
|
||||
*/
|
||||
protected void writeOptionalAttributes(TagWriter tagWriter) throws JspException {
|
||||
|
|
@ -403,6 +433,12 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
writeOptionalAttribute(tagWriter, ONKEYPRESS_ATTRIBUTE, getOnkeypress());
|
||||
writeOptionalAttribute(tagWriter, ONKEYUP_ATTRIBUTE, getOnkeyup());
|
||||
writeOptionalAttribute(tagWriter, ONKEYDOWN_ATTRIBUTE, getOnkeydown());
|
||||
|
||||
if (!CollectionUtils.isEmpty(this.dynamicAttributes)) {
|
||||
for (String attr : this.dynamicAttributes.keySet()) {
|
||||
tagWriter.writeOptionalAttributeValue(attr, getDisplayString(this.dynamicAttributes.get(attr)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -190,6 +190,7 @@
|
|||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
<dynamic-attributes>true</dynamic-attributes>
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
|
|
@ -383,6 +384,7 @@
|
|||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
<dynamic-attributes>true</dynamic-attributes>
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
|
|
@ -582,6 +584,7 @@
|
|||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
<dynamic-attributes>true</dynamic-attributes>
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
|
|
@ -794,6 +797,7 @@
|
|||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
<dynamic-attributes>true</dynamic-attributes>
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
|
|
@ -944,6 +948,7 @@
|
|||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
<dynamic-attributes>true</dynamic-attributes>
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
|
|
@ -1089,6 +1094,7 @@
|
|||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
<dynamic-attributes>true</dynamic-attributes>
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
|
|
@ -1258,6 +1264,7 @@
|
|||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
<dynamic-attributes>true</dynamic-attributes>
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
|
|
@ -1445,6 +1452,7 @@
|
|||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
<dynamic-attributes>true</dynamic-attributes>
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
|
|
@ -1614,6 +1622,7 @@
|
|||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
<dynamic-attributes>true</dynamic-attributes>
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
|
|
@ -1801,6 +1810,7 @@
|
|||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
<dynamic-attributes>true</dynamic-attributes>
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
|
|
@ -1982,6 +1992,7 @@
|
|||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
<dynamic-attributes>true</dynamic-attributes>
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
|
|
@ -2119,6 +2130,7 @@
|
|||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
<dynamic-attributes>true</dynamic-attributes>
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
|
|
@ -2252,6 +2264,7 @@
|
|||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
<dynamic-attributes>true</dynamic-attributes>
|
||||
</tag>
|
||||
|
||||
</taglib>
|
||||
|
|
@ -39,6 +39,7 @@ import org.springframework.validation.BindingResult;
|
|||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class CheckboxTagTests extends AbstractFormTagTests {
|
||||
|
||||
|
|
@ -76,6 +77,35 @@ public class CheckboxTagTests extends AbstractFormTagTests {
|
|||
assertEquals("true", checkboxElement.attribute("value").getValue());
|
||||
}
|
||||
|
||||
public void testWithSingleValueBooleanObjectCheckedAndDynamicAttributes() throws Exception {
|
||||
String dynamicAttribute1 = "attr1";
|
||||
String dynamicAttribute2 = "attr2";
|
||||
|
||||
this.tag.setPath("someBoolean");
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute1, dynamicAttribute1);
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute2, dynamicAttribute2);
|
||||
|
||||
int result = this.tag.doStartTag();
|
||||
assertEquals(Tag.SKIP_BODY, result);
|
||||
String output = getOutput();
|
||||
|
||||
// wrap the output so it is valid XML
|
||||
output = "<doc>" + output + "</doc>";
|
||||
|
||||
SAXReader reader = new SAXReader();
|
||||
Document document = reader.read(new StringReader(output));
|
||||
Element rootElement = document.getRootElement();
|
||||
assertEquals("Both tag and hidden element not rendered", 2, rootElement.elements().size());
|
||||
Element checkboxElement = (Element) rootElement.elements().get(0);
|
||||
assertEquals("input", checkboxElement.getName());
|
||||
assertEquals("checkbox", checkboxElement.attribute("type").getValue());
|
||||
assertEquals("someBoolean", checkboxElement.attribute("name").getValue());
|
||||
assertEquals("checked", checkboxElement.attribute("checked").getValue());
|
||||
assertEquals("true", checkboxElement.attribute("value").getValue());
|
||||
assertEquals(dynamicAttribute1, checkboxElement.attribute(dynamicAttribute1).getValue());
|
||||
assertEquals(dynamicAttribute2, checkboxElement.attribute(dynamicAttribute2).getValue());
|
||||
}
|
||||
|
||||
public void testWithSingleValueBooleanChecked() throws Exception {
|
||||
this.tag.setPath("jedi");
|
||||
int result = this.tag.doStartTag();
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ import org.springframework.validation.BindingResult;
|
|||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
* @author Benjamin Hoffmann
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class CheckboxesTagTests extends AbstractFormTagTests {
|
||||
|
||||
|
|
@ -100,6 +101,59 @@ public class CheckboxesTagTests extends AbstractFormTagTests {
|
|||
assertEquals("baz", spanElement3.getStringValue());
|
||||
}
|
||||
|
||||
public void testWithMultiValueArrayAndDynamicAttributes() throws Exception {
|
||||
String dynamicAttribute1 = "attr1";
|
||||
String dynamicAttribute2 = "attr2";
|
||||
|
||||
this.tag.setPath("stringArray");
|
||||
this.tag.setItems(new Object[] {"foo", "bar", "baz"});
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute1, dynamicAttribute1);
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute2, dynamicAttribute2);
|
||||
|
||||
int result = this.tag.doStartTag();
|
||||
assertEquals(Tag.SKIP_BODY, result);
|
||||
|
||||
String output = getOutput();
|
||||
|
||||
// wrap the output so it is valid XML
|
||||
output = "<doc>" + output + "</doc>";
|
||||
SAXReader reader = new SAXReader();
|
||||
Document document = reader.read(new StringReader(output));
|
||||
Element spanElement1 = (Element) document.getRootElement().elements().get(0);
|
||||
Element checkboxElement1 = (Element) spanElement1.elements().get(0);
|
||||
assertEquals("input", checkboxElement1.getName());
|
||||
assertEquals("checkbox", checkboxElement1.attribute("type").getValue());
|
||||
assertEquals("stringArray", checkboxElement1.attribute("name").getValue());
|
||||
assertEquals("checked", checkboxElement1.attribute("checked").getValue());
|
||||
assertEquals("foo", checkboxElement1.attribute("value").getValue());
|
||||
assertEquals("foo", spanElement1.getStringValue());
|
||||
assertEquals(dynamicAttribute1, checkboxElement1.attribute(dynamicAttribute1).getValue());
|
||||
assertEquals(dynamicAttribute2, checkboxElement1.attribute(dynamicAttribute2).getValue());
|
||||
|
||||
Element spanElement2 = (Element) document.getRootElement().elements().get(1);
|
||||
Element checkboxElement2 = (Element) spanElement2.elements().get(0);
|
||||
assertEquals("input", checkboxElement2.getName());
|
||||
assertEquals("checkbox", checkboxElement2.attribute("type").getValue());
|
||||
assertEquals("stringArray", checkboxElement2.attribute("name").getValue());
|
||||
assertEquals("checked", checkboxElement2.attribute("checked").getValue());
|
||||
assertEquals("bar", checkboxElement2.attribute("value").getValue());
|
||||
assertEquals("bar", spanElement2.getStringValue());
|
||||
assertEquals(dynamicAttribute1, checkboxElement2.attribute(dynamicAttribute1).getValue());
|
||||
assertEquals(dynamicAttribute2, checkboxElement2.attribute(dynamicAttribute2).getValue());
|
||||
|
||||
Element spanElement3 = (Element) document.getRootElement().elements().get(2);
|
||||
Element checkboxElement3 = (Element) spanElement3.elements().get(0);
|
||||
assertEquals("input", checkboxElement3.getName());
|
||||
assertEquals("checkbox", checkboxElement3.attribute("type").getValue());
|
||||
assertEquals("stringArray", checkboxElement3.attribute("name").getValue());
|
||||
assertNull("not checked", checkboxElement3.attribute("checked"));
|
||||
assertEquals("baz", checkboxElement3.attribute("value").getValue());
|
||||
assertEquals("baz", spanElement3.getStringValue());
|
||||
assertEquals(dynamicAttribute1, checkboxElement3.attribute(dynamicAttribute1).getValue());
|
||||
assertEquals(dynamicAttribute2, checkboxElement3.attribute(dynamicAttribute2).getValue());
|
||||
|
||||
}
|
||||
|
||||
public void testWithMultiValueArrayWithDelimiter() throws Exception {
|
||||
this.tag.setDelimiter("<br/>");
|
||||
this.tag.setPath("stringArray");
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import org.springframework.web.servlet.tags.RequestContextAwareTag;
|
|||
* @author Rick Evans
|
||||
* @author Juergen Hoeller
|
||||
* @author Mark Fisher
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class ErrorsTagTests extends AbstractFormTagTests {
|
||||
|
||||
|
|
@ -160,6 +161,40 @@ public class ErrorsTagTests extends AbstractFormTagTests {
|
|||
assertBlockTagContains(output, "Too Short");
|
||||
}
|
||||
|
||||
public void testWithErrorsAndDynamicAttributes() throws Exception {
|
||||
String dynamicAttribute1 = "attr1";
|
||||
String dynamicAttribute2 = "attr2";
|
||||
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute1, dynamicAttribute1);
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute2, dynamicAttribute2);
|
||||
|
||||
// construct an errors instance of the tag
|
||||
TestBean target = new TestBean();
|
||||
target.setName("Rob Harrop");
|
||||
Errors errors = new BeanPropertyBindingResult(target, COMMAND_NAME);
|
||||
errors.rejectValue("name", "some.code", "Default Message");
|
||||
errors.rejectValue("name", "too.short", "Too Short");
|
||||
|
||||
exposeBindingResult(errors);
|
||||
|
||||
int result = this.tag.doStartTag();
|
||||
assertEquals(BodyTag.EVAL_BODY_BUFFERED, result);
|
||||
|
||||
result = this.tag.doEndTag();
|
||||
assertEquals(Tag.EVAL_PAGE, result);
|
||||
|
||||
String output = getOutput();
|
||||
assertElementTagOpened(output);
|
||||
assertElementTagClosed(output);
|
||||
|
||||
assertContainsAttribute(output, "id", "name.errors");
|
||||
assertContainsAttribute(output, dynamicAttribute1, dynamicAttribute1);
|
||||
assertContainsAttribute(output, dynamicAttribute2, dynamicAttribute2);
|
||||
assertBlockTagContains(output, "<br/>");
|
||||
assertBlockTagContains(output, "Default Message");
|
||||
assertBlockTagContains(output, "Too Short");
|
||||
}
|
||||
|
||||
public void testWithEscapedErrors() throws Exception {
|
||||
// construct an errors instance of the tag
|
||||
TestBean target = new TestBean();
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import org.springframework.mock.web.MockHttpServletRequest;
|
|||
* @author Rick Evans
|
||||
* @author Juergen Hoeller
|
||||
* @author Scott Andrews
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class FormTagTests extends AbstractHtmlElementTagTests {
|
||||
|
||||
|
|
@ -68,6 +69,8 @@ public class FormTagTests extends AbstractHtmlElementTagTests {
|
|||
String autocomplete = "off";
|
||||
String cssClass = "myClass";
|
||||
String cssStyle = "myStyle";
|
||||
String dynamicAttribute1 = "attr1";
|
||||
String dynamicAttribute2 = "attr2";
|
||||
|
||||
this.tag.setName(name);
|
||||
this.tag.setCssClass(cssClass);
|
||||
|
|
@ -81,6 +84,8 @@ public class FormTagTests extends AbstractHtmlElementTagTests {
|
|||
this.tag.setOnsubmit(onsubmit);
|
||||
this.tag.setOnreset(onreset);
|
||||
this.tag.setAutocomplete(autocomplete);
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute1, dynamicAttribute1);
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute2, dynamicAttribute2);
|
||||
|
||||
int result = this.tag.doStartTag();
|
||||
assertEquals(Tag.EVAL_BODY_INCLUDE, result);
|
||||
|
|
@ -110,6 +115,8 @@ public class FormTagTests extends AbstractHtmlElementTagTests {
|
|||
assertContainsAttribute(output, "autocomplete", autocomplete);
|
||||
assertContainsAttribute(output, "id", commandName);
|
||||
assertContainsAttribute(output, "name", name);
|
||||
assertContainsAttribute(output, dynamicAttribute1, dynamicAttribute1);
|
||||
assertContainsAttribute(output, dynamicAttribute2, dynamicAttribute2);
|
||||
}
|
||||
|
||||
public void testWithActionFromRequest() throws Exception {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import org.springframework.web.servlet.tags.NestedPathTag;
|
|||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Rick Evans
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class InputTagTests extends AbstractFormTagTests {
|
||||
|
||||
|
|
@ -149,6 +150,8 @@ public class InputTagTests extends AbstractFormTagTests {
|
|||
String onselect = "doSelect()";
|
||||
String readonly = "true";
|
||||
String autocomplete = "off";
|
||||
String dynamicAttribute1 = "attr1";
|
||||
String dynamicAttribute2 = "attr2";
|
||||
|
||||
this.tag.setId(id);
|
||||
this.tag.setPath("name");
|
||||
|
|
@ -179,6 +182,8 @@ public class InputTagTests extends AbstractFormTagTests {
|
|||
this.tag.setOnselect(onselect);
|
||||
this.tag.setReadonly(readonly);
|
||||
this.tag.setAutocomplete(autocomplete);
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute1, dynamicAttribute1);
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute2, dynamicAttribute2);
|
||||
|
||||
assertEquals(Tag.SKIP_BODY, this.tag.doStartTag());
|
||||
|
||||
|
|
@ -217,6 +222,8 @@ public class InputTagTests extends AbstractFormTagTests {
|
|||
assertContainsAttribute(output, "onselect", onselect);
|
||||
assertContainsAttribute(output, "readonly", "readonly");
|
||||
assertContainsAttribute(output, "autocomplete", autocomplete);
|
||||
assertContainsAttribute(output, dynamicAttribute1, dynamicAttribute1);
|
||||
assertContainsAttribute(output, dynamicAttribute2, dynamicAttribute2);
|
||||
}
|
||||
|
||||
public void testWithNestedBind() throws Exception {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import org.springframework.web.servlet.tags.NestedPathTag;
|
|||
* @author Rob Harrop
|
||||
* @author Rick Evans
|
||||
* @author Juergen Hoeller
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class LabelTagTests extends AbstractFormTagTests {
|
||||
|
||||
|
|
@ -71,6 +72,33 @@ public class LabelTagTests extends AbstractFormTagTests {
|
|||
assertTrue(output.endsWith("</label>"));
|
||||
}
|
||||
|
||||
public void testSimpleRenderWithDynamicAttributes() throws Exception {
|
||||
String dynamicAttribute1 = "attr1";
|
||||
String dynamicAttribute2 = "attr2";
|
||||
|
||||
this.tag.setPath("name");
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute1, dynamicAttribute1);
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute2, dynamicAttribute2);
|
||||
|
||||
int startResult = this.tag.doStartTag();
|
||||
int endResult = this.tag.doEndTag();
|
||||
|
||||
assertEquals(Tag.EVAL_BODY_INCLUDE, startResult);
|
||||
assertEquals(Tag.EVAL_PAGE, endResult);
|
||||
|
||||
String output = getOutput();
|
||||
// we are using a nexted path (see extendPageContext(..)), so...
|
||||
assertContainsAttribute(output, "for", "spouse.name");
|
||||
assertContainsAttribute(output, dynamicAttribute1, dynamicAttribute1);
|
||||
assertContainsAttribute(output, dynamicAttribute2, dynamicAttribute2);
|
||||
// name attribute is not supported by <label/>
|
||||
assertAttributeNotPresent(output, "name");
|
||||
// id attribute is supported, but we don't want it
|
||||
assertAttributeNotPresent(output, "id");
|
||||
assertTrue(output.startsWith("<label "));
|
||||
assertTrue(output.endsWith("</label>"));
|
||||
}
|
||||
|
||||
public void testSimpleRenderWithMapElement() throws Exception {
|
||||
this.tag.setPath("someMap[1]");
|
||||
int startResult = this.tag.doStartTag();
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import org.springframework.web.servlet.support.BindStatus;
|
|||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @author Rick Evans
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class OptionTagTests extends AbstractHtmlElementTagTests {
|
||||
|
||||
|
|
@ -96,6 +97,31 @@ public class OptionTagTests extends AbstractHtmlElementTagTests {
|
|||
assertBlockTagContains(output, "Bar");
|
||||
}
|
||||
|
||||
public void testRenderWithDynamicAttributes() throws Exception {
|
||||
String dynamicAttribute1 = "attr1";
|
||||
String dynamicAttribute2 = "attr2";
|
||||
|
||||
getPageContext().setAttribute(SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, new BindStatus(getRequestContext(), "testBean.name", false));
|
||||
this.tag.setValue("bar");
|
||||
this.tag.setLabel("Bar");
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute1, dynamicAttribute1);
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute2, dynamicAttribute2);
|
||||
|
||||
int result = this.tag.doStartTag();
|
||||
assertEquals(BodyTag.EVAL_BODY_BUFFERED, result);
|
||||
result = this.tag.doEndTag();
|
||||
assertEquals(Tag.EVAL_PAGE, result);
|
||||
|
||||
String output = getOutput();
|
||||
|
||||
assertOptionTagOpened(output);
|
||||
assertOptionTagClosed(output);
|
||||
assertContainsAttribute(output, "value", "bar");
|
||||
assertContainsAttribute(output, dynamicAttribute1, dynamicAttribute1);
|
||||
assertContainsAttribute(output, dynamicAttribute2, dynamicAttribute2);
|
||||
assertBlockTagContains(output, "Bar");
|
||||
}
|
||||
|
||||
public void testRenderSelected() throws Exception {
|
||||
getPageContext().setAttribute(SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, new BindStatus(getRequestContext(), "testBean.name", false));
|
||||
this.tag.setId("myOption");
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ import org.springframework.web.servlet.tags.RequestContextAwareTag;
|
|||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @author Scott Andrews
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public final class OptionsTagTests extends AbstractHtmlElementTagTests {
|
||||
|
||||
|
|
@ -98,6 +99,43 @@ public final class OptionsTagTests extends AbstractHtmlElementTagTests {
|
|||
assertEquals("CLICK", element.attribute("onclick").getValue());
|
||||
}
|
||||
|
||||
public void testWithCollectionAndDynamicAttributes() throws Exception {
|
||||
String dynamicAttribute1 = "attr1";
|
||||
String dynamicAttribute2 = "attr2";
|
||||
|
||||
getPageContext().setAttribute(
|
||||
SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, new BindStatus(getRequestContext(), "testBean.country", false));
|
||||
|
||||
this.tag.setItems("${countries}");
|
||||
this.tag.setItemValue("isoCode");
|
||||
this.tag.setItemLabel("name");
|
||||
this.tag.setId("myOption");
|
||||
this.tag.setCssClass("myClass");
|
||||
this.tag.setOnclick("CLICK");
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute1, dynamicAttribute1);
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute2, dynamicAttribute2);
|
||||
|
||||
int result = this.tag.doStartTag();
|
||||
assertEquals(Tag.SKIP_BODY, result);
|
||||
String output = getOutput();
|
||||
output = "<doc>" + output + "</doc>";
|
||||
|
||||
SAXReader reader = new SAXReader();
|
||||
Document document = reader.read(new StringReader(output));
|
||||
Element rootElement = document.getRootElement();
|
||||
|
||||
List children = rootElement.elements();
|
||||
assertEquals("Incorrect number of children", 4, children.size());
|
||||
|
||||
Element element = (Element) rootElement.selectSingleNode("option[@value = 'UK']");
|
||||
assertEquals("UK node not selected", "selected", element.attribute("selected").getValue());
|
||||
assertEquals("myOption3", element.attribute("id").getValue());
|
||||
assertEquals("myClass", element.attribute("class").getValue());
|
||||
assertEquals("CLICK", element.attribute("onclick").getValue());
|
||||
assertEquals(dynamicAttribute1, element.attribute(dynamicAttribute1).getValue());
|
||||
assertEquals(dynamicAttribute2, element.attribute(dynamicAttribute2).getValue());
|
||||
}
|
||||
|
||||
public void testWithCollectionAndCustomEditor() throws Exception {
|
||||
PropertyEditor propertyEditor = new SimpleFloatEditor();
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import javax.servlet.jsp.tagext.Tag;
|
|||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Rick Evans
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class PasswordInputTagTests extends InputTagTests {
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import org.springframework.validation.BindingResult;
|
|||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class RadioButtonTagTests extends AbstractFormTagTests {
|
||||
|
||||
|
|
@ -51,6 +52,29 @@ public class RadioButtonTagTests extends AbstractFormTagTests {
|
|||
}
|
||||
|
||||
public void testWithCheckedValue() throws Exception {
|
||||
String dynamicAttribute1 = "attr1";
|
||||
String dynamicAttribute2 = "attr2";
|
||||
|
||||
this.tag.setPath("sex");
|
||||
this.tag.setValue("M");
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute1, dynamicAttribute1);
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute2, dynamicAttribute2);
|
||||
|
||||
int result = this.tag.doStartTag();
|
||||
assertEquals(Tag.SKIP_BODY, result);
|
||||
|
||||
String output = getOutput();
|
||||
assertTagOpened(output);
|
||||
assertTagClosed(output);
|
||||
assertContainsAttribute(output, "name", "sex");
|
||||
assertContainsAttribute(output, "type", "radio");
|
||||
assertContainsAttribute(output, "value", "M");
|
||||
assertContainsAttribute(output, "checked", "checked");
|
||||
assertContainsAttribute(output, dynamicAttribute1, dynamicAttribute1);
|
||||
assertContainsAttribute(output, dynamicAttribute2, dynamicAttribute2);
|
||||
}
|
||||
|
||||
public void testWithCheckedValueAndDynamicAttributes() throws Exception {
|
||||
this.tag.setPath("sex");
|
||||
this.tag.setValue("M");
|
||||
int result = this.tag.doStartTag();
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ import org.springframework.validation.BindingResult;
|
|||
* @author Thomas Risberg
|
||||
* @author Juergen Hoeller
|
||||
* @author Scott Andrews
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public final class RadioButtonsTagTests extends AbstractFormTagTests {
|
||||
|
||||
|
|
@ -98,6 +99,59 @@ public final class RadioButtonsTagTests extends AbstractFormTagTests {
|
|||
assertEquals("baz", spanElement3.getStringValue());
|
||||
}
|
||||
|
||||
public void testWithMultiValueArrayAndDynamicAttributes() throws Exception {
|
||||
String dynamicAttribute1 = "attr1";
|
||||
String dynamicAttribute2 = "attr2";
|
||||
|
||||
this.tag.setPath("stringArray");
|
||||
this.tag.setItems(new Object[] {"foo", "bar", "baz"});
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute1, dynamicAttribute1);
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute2, dynamicAttribute2);
|
||||
|
||||
int result = this.tag.doStartTag();
|
||||
assertEquals(Tag.SKIP_BODY, result);
|
||||
|
||||
String output = getOutput();
|
||||
|
||||
// wrap the output so it is valid XML
|
||||
output = "<doc>" + output + "</doc>";
|
||||
SAXReader reader = new SAXReader();
|
||||
Document document = reader.read(new StringReader(output));
|
||||
Element spanElement1 = (Element) document.getRootElement().elements().get(0);
|
||||
Element radioButtonElement1 = (Element) spanElement1.elements().get(0);
|
||||
assertEquals("input", radioButtonElement1.getName());
|
||||
assertEquals("radio", radioButtonElement1.attribute("type").getValue());
|
||||
assertEquals("stringArray", radioButtonElement1.attribute("name").getValue());
|
||||
assertEquals("checked", radioButtonElement1.attribute("checked").getValue());
|
||||
assertEquals("foo", radioButtonElement1.attribute("value").getValue());
|
||||
assertEquals("foo", spanElement1.getStringValue());
|
||||
assertEquals(dynamicAttribute1, radioButtonElement1.attribute(dynamicAttribute1).getValue());
|
||||
assertEquals(dynamicAttribute2, radioButtonElement1.attribute(dynamicAttribute2).getValue());
|
||||
|
||||
Element spanElement2 = (Element) document.getRootElement().elements().get(1);
|
||||
Element radioButtonElement2 = (Element) spanElement2.elements().get(0);
|
||||
assertEquals("input", radioButtonElement2.getName());
|
||||
assertEquals("radio", radioButtonElement2.attribute("type").getValue());
|
||||
assertEquals("stringArray", radioButtonElement2.attribute("name").getValue());
|
||||
assertEquals("checked", radioButtonElement2.attribute("checked").getValue());
|
||||
assertEquals("bar", radioButtonElement2.attribute("value").getValue());
|
||||
assertEquals("bar", spanElement2.getStringValue());
|
||||
assertEquals(dynamicAttribute1, radioButtonElement2.attribute(dynamicAttribute1).getValue());
|
||||
assertEquals(dynamicAttribute2, radioButtonElement2.attribute(dynamicAttribute2).getValue());
|
||||
|
||||
Element spanElement3 = (Element) document.getRootElement().elements().get(2);
|
||||
Element radioButtonElement3 = (Element) spanElement3.elements().get(0);
|
||||
assertEquals("input", radioButtonElement3.getName());
|
||||
assertEquals("radio", radioButtonElement3.attribute("type").getValue());
|
||||
assertEquals("stringArray", radioButtonElement3.attribute("name").getValue());
|
||||
assertNull("not checked", radioButtonElement3.attribute("checked"));
|
||||
assertEquals("baz", radioButtonElement3.attribute("value").getValue());
|
||||
assertEquals("baz", spanElement3.getStringValue());
|
||||
assertEquals(dynamicAttribute1, radioButtonElement3.attribute(dynamicAttribute1).getValue());
|
||||
assertEquals(dynamicAttribute2, radioButtonElement3.attribute(dynamicAttribute2).getValue());
|
||||
|
||||
}
|
||||
|
||||
public void testWithMultiValueArrayWithDelimiter() throws Exception {
|
||||
this.tag.setDelimiter("<br/>");
|
||||
this.tag.setPath("stringArray");
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ import org.springframework.web.servlet.tags.TransformTag;
|
|||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class SelectTagTests extends AbstractFormTagTests {
|
||||
|
||||
|
|
@ -69,6 +70,24 @@ public class SelectTagTests extends AbstractFormTagTests {
|
|||
this.tag.setPageContext(getPageContext());
|
||||
}
|
||||
|
||||
public void testDynamicAttributes() throws JspException {
|
||||
String dynamicAttribute1 = "attr1";
|
||||
String dynamicAttribute2 = "attr2";
|
||||
|
||||
this.tag.setPath("country");
|
||||
this.tag.setItems(Collections.EMPTY_LIST);
|
||||
this.tag.setItemValue("isoCode");
|
||||
this.tag.setItemLabel("name");
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute1, dynamicAttribute1);
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute2, dynamicAttribute2);
|
||||
|
||||
int result = this.tag.doStartTag();
|
||||
assertEquals(Tag.SKIP_BODY, result);
|
||||
|
||||
String output = getOutput();
|
||||
assertContainsAttribute(output, dynamicAttribute1, dynamicAttribute1);
|
||||
assertContainsAttribute(output, dynamicAttribute2, dynamicAttribute2);
|
||||
}
|
||||
|
||||
public void testEmptyItems() throws Exception {
|
||||
this.tag.setPath("country");
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import org.springframework.validation.BeanPropertyBindingResult;
|
|||
* @author Rob Harrop
|
||||
* @author Rick Evans
|
||||
* @author Juergen Hoeller
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class TextareaTagTests extends AbstractFormTagTests {
|
||||
|
||||
|
|
@ -52,6 +53,24 @@ public class TextareaTagTests extends AbstractFormTagTests {
|
|||
assertBlockTagContains(output, "Rob");
|
||||
}
|
||||
|
||||
public void testSimpleBindWithDynamicAttributes() throws Exception {
|
||||
String dynamicAttribute1 = "attr1";
|
||||
String dynamicAttribute2 = "attr2";
|
||||
|
||||
this.tag.setPath("name");
|
||||
this.tag.setReadonly("true");
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute1, dynamicAttribute1);
|
||||
this.tag.setDynamicAttribute(null, dynamicAttribute2, dynamicAttribute2);
|
||||
|
||||
assertEquals(Tag.SKIP_BODY, this.tag.doStartTag());
|
||||
String output = getOutput();
|
||||
assertContainsAttribute(output, "name", "name");
|
||||
assertContainsAttribute(output, "readonly", "readonly");
|
||||
assertContainsAttribute(output, dynamicAttribute1, dynamicAttribute1);
|
||||
assertContainsAttribute(output, dynamicAttribute2, dynamicAttribute2);
|
||||
assertBlockTagContains(output, "Rob");
|
||||
}
|
||||
|
||||
public void testComplexBind() throws Exception {
|
||||
String onselect = "doSelect()";
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue