Generate bracketless tag id in Velocity forms

Before this change if Velocity Spring form macro was bound to a path
which contains square brackets, those brackets would also appear in id
of generated tag, making the id invalid.

As of this fix all Velocity Spring form macros generate tag with id
that does not contain square brackets.

Issue: SPR-5172
This commit is contained in:
Rob Winch 2014-07-21 13:09:28 -05:00 committed by Rossen Stoyanchev
parent 73267d7523
commit 1b53882f55
3 changed files with 101 additions and 9 deletions

View File

@ -112,7 +112,7 @@
*#
#macro( springFormInput $path $attributes )
#springBind($path)
<input type="text" id="${status.expression}" name="${status.expression}" value="$!status.value" ${attributes}#springCloseTag()
<input type="text" id="#xmlId(${status.expression})" name="${status.expression}" value="$!status.value" ${attributes}#springCloseTag()
#end
#**
@ -129,7 +129,7 @@
*#
#macro( springFormPasswordInput $path $attributes )
#springBind($path)
<input type="password" id="${status.expression}" name="${status.expression}" value="" ${attributes}#springCloseTag()
<input type="password" id="#xmlId(${status.expression})" name="${status.expression}" value="" ${attributes}#springCloseTag()
#end
#**
@ -145,7 +145,7 @@
*#
#macro( springFormHiddenInput $path $attributes )
#springBind($path)
<input type="hidden" id="${status.expression}" name="${status.expression}" value="$!status.value" ${attributes}#springCloseTag()
<input type="hidden" id="#xmlId(${status.expression})" name="${status.expression}" value="$!status.value" ${attributes}#springCloseTag()
#end
#**
@ -161,7 +161,7 @@
*#
#macro( springFormTextarea $path $attributes )
#springBind($path)
<textarea id="${status.expression}" name="${status.expression}" ${attributes}>$!status.value</textarea>
<textarea id="#xmlId(${status.expression})" name="${status.expression}" ${attributes}>$!status.value</textarea>
#end
#**
@ -182,7 +182,7 @@
*#
#macro( springFormSingleSelect $path $options $attributes )
#springBind($path)
<select id="${status.expression}" name="${status.expression}" ${attributes}>
<select id="#xmlId(${status.expression})" name="${status.expression}" ${attributes}>
#foreach($option in $options.keySet())
<option value="${option}"
#if ("$!status.value" == "$option") selected="selected" #end>
@ -204,7 +204,7 @@
*#
#macro( springFormMultiSelect $path $options $attributes )
#springBind($path)
<select multiple="multiple" id="${status.expression}" name="${status.expression}" ${attributes}>
<select multiple="multiple" id="#xmlId(${status.expression})" name="${status.expression}" ${attributes}>
#foreach($option in $options.keySet())
<option value="${option}"
#foreach($item in $status.actualValue)
@ -274,8 +274,8 @@
*#
#macro( springFormCheckbox $path $attributes )
#springBind($path)
<input type="hidden" name="_${status.expression}" value="on"/>
<input type="checkbox" id="${status.expression}" name="${status.expression}"#if ("$!{status.value}"=="true") checked="checked"#end ${attributes}/>
<input type="hidden" name="_#xmlId(${status.expression})" value="on"/>
<input type="checkbox" id="#xmlId(${status.expression})" name="${status.expression}"#if ("$!{status.value}"=="true") checked="checked"#end ${attributes}/>
#end
#**
@ -316,7 +316,7 @@
*#
#macro( springCloseTag )#if ($springXhtmlCompliant)/>#else>#end #end
#macro( xmlId $id)#if($id)$id.replaceAll("\[","").replaceAll("\]","")#else$id#end#end

View File

@ -190,4 +190,66 @@ public class VelocityMacroTests extends TestCase {
}
}
// SPR-5172
public void testIdContainsBraces() throws Exception {
DummyMacroRequestContext rc = new DummyMacroRequestContext(request);
Map<String, String> msgMap = new HashMap<String, String>();
msgMap.put("hello", "Howdy");
msgMap.put("world", "Mundo");
rc.setMessageMap(msgMap);
Map<String, String> themeMsgMap = new HashMap<String, String>();
themeMsgMap.put("hello", "Howdy!");
themeMsgMap.put("world", "Mundo!");
rc.setThemeMessageMap(themeMsgMap);
rc.setContextPath("/springtest");
TestBean darren = new TestBean("Darren", 99);
TestBean fred = new TestBean("Fred");
fred.setJedi(true);
darren.setSpouse(fred);
darren.setJedi(true);
darren.setStringArray(new String[] {"John", "Fred"});
request.setAttribute("command", darren);
Map<String, String> names = new HashMap<String, String>();
names.put("Darren", "Darren Davison");
names.put("John", "John Doe");
names.put("Fred", "Fred Bloggs");
VelocityConfigurer vc = new VelocityConfigurer();
vc.setPreferFileSystemAccess(false);
VelocityEngine ve = vc.createVelocityEngine();
Map<String, Object> model = new HashMap<String, Object>();
model.put("command", darren);
model.put("springMacroRequestContext", rc);
model.put("nameOptionMap", names);
VelocityView view = new VelocityView();
view.setBeanName("myView");
view.setUrl("org/springframework/web/servlet/view/velocity/test-spr5172.vm");
view.setEncoding("UTF-8");
view.setExposeSpringMacroHelpers(false);
view.setVelocityEngine(ve);
view.render(model, request, response);
// tokenize output and ignore whitespace
String output = response.getContentAsString();
String[] tokens = StringUtils.tokenizeToStringArray(output, "\t\n");
for (int i = 0; i < tokens.length; i++) {
if (tokens[i].equals("FORM1")) assertEquals("<input type=\"text\" id=\"spouses0.name\" name=\"spouses[0].name\" value=\"Fred\" >", tokens[i + 1]); //
if (tokens[i].equals("FORM2")) assertEquals("<textarea id=\"spouses0.name\" name=\"spouses[0].name\" >Fred</textarea>", tokens[i + 1]);
if (tokens[i].equals("FORM3")) assertEquals("<select id=\"spouses0.name\" name=\"spouses[0].name\" >", tokens[i + 1]);
if (tokens[i].equals("FORM4")) assertEquals("<select multiple=\"multiple\" id=\"spouses\" name=\"spouses\" >", tokens[i + 1]);
if (tokens[i].equals("FORM5")) assertEquals("<input type=\"radio\" name=\"spouses[0].name\" value=\"Darren\"", tokens[i + 1]);
if (tokens[i].equals("FORM6")) assertEquals("<input type=\"password\" id=\"spouses0.name\" name=\"spouses[0].name\" value=\"\" >", tokens[i + 1]);
if (tokens[i].equals("FORM7")) assertEquals("<input type=\"hidden\" id=\"spouses0.name\" name=\"spouses[0].name\" value=\"Fred\" >", tokens[i + 1]);
if (tokens[i].equals("FORM8")) assertEquals("<input type=\"hidden\" name=\"_spouses0.name\" value=\"on\"/>", tokens[i + 1]);
if (tokens[i].equals("FORM8")) assertEquals("<input type=\"checkbox\" id=\"spouses0.name\" name=\"spouses[0].name\" />", tokens[i + 2]);
if (tokens[i].equals("FORM9")) assertEquals("<input type=\"hidden\" name=\"_spouses0.jedi\" value=\"on\"/>", tokens[i + 1]);
if (tokens[i].equals("FORM9")) assertEquals("<input type=\"checkbox\" id=\"spouses0.jedi\" name=\"spouses[0].jedi\" checked=\"checked\" />", tokens[i + 2]);
}
}
}

View File

@ -0,0 +1,30 @@
##
## test template for Velocity macro test class
##
FORM1
#springFormInput("command.spouses[0].name" "")
FORM2
#springFormTextarea("command.spouses[0].name" "")
FORM3
#springFormSingleSelect("command.spouses[0].name" $nameOptionMap "")
FORM4
#springFormMultiSelect("command.spouses" $nameOptionMap "")
FORM5
#springFormRadioButtons("command.spouses[0].name" $nameOptionMap " " "")
FORM6
#springFormPasswordInput("command.spouses[0].name" "")
FORM7
#springFormHiddenInput("command.spouses[0].name" "")
FORM8
#springFormCheckbox("command.spouses[0].name" "")
FORM9
#springFormCheckbox("command.spouses[0].jedi" "")