Permalink
Browse files

support form html5's required attribute

html5 supports usage of a 'required' attribute to indicate mandatory fields.
Previously it was odd behaviour because <g:textField ... required="false"/> in fact creates a mandatory field,
because the browser does not look at the value of required attribute, it just uses it's existence.
Now the required attribute is only rendered, of the value of attrs.requires evaluates to true
  • Loading branch information...
1 parent af484a8 commit 484a933ab9203bb8b2491cf74755acba76e435e8 @sarmbruster committed Oct 3, 2011
@@ -117,6 +117,7 @@ class FormTagLib {
def fieldImpl(out, attrs) {
resolveAttributes(attrs)
+ handleRequiredAttribute(attrs)
attrs.id = attrs.id ?: attrs.name
out << "<input type=\"${attrs.remove('type')}\" "
outputAttributes(attrs, out)
@@ -155,6 +156,8 @@ class FormTagLib {
if (checked instanceof String) checked = Boolean.valueOf(checked)
+ handleRequiredAttribute(attrs)
+
if (value == null) value = false
out << "<input type=\"hidden\" name=\"_${name}\" /><input type=\"checkbox\" name=\"${name}\" "
@@ -233,6 +236,18 @@ class FormTagLib {
}
/**
+ * handle HTML's 'required' attribute: only add it if it's value is true in HTML even 'required="false"' marks the field as required
+ * @param attrs
+ */
+ void handleRequiredAttribute(attrs) {
+ def requiredString = attrs.remove('required')
+ Boolean required = Boolean.valueOf(requiredString)
+ if (required) {
+ attrs.required = true
+ }
+ }
+
+ /**
* Dump out attributes in HTML compliant fashion.
*/
void outputAttributes(attrs, writer) {
@@ -759,6 +774,7 @@ class FormTagLib {
if (disabled && Boolean.valueOf(disabled)) {
attrs.disabled = 'disabled'
}
+ handleRequiredAttribute(attrs)
writer << "<select name=\"${attrs.remove('name')?.encodeAsHTML()}\" "
// process remaining attributes
@@ -900,6 +916,8 @@ class FormTagLib {
attrs.disabled = 'disabled'
}
def checked = attrs.remove('checked') ? true : false
+ handleRequiredAttribute(attrs)
+
out << "<input type=\"radio\" name=\"${name}\"${ checked ? ' checked="checked" ' : ' '}value=\"${value?.toString()?.encodeAsHTML()}\" "
// process remaining attributes
outputAttributes(attrs, out)
@@ -921,6 +939,8 @@ class FormTagLib {
def values = attrs.remove('values')
def labels = attrs.remove('labels')
def name = attrs.remove('name')
+ handleRequiredAttribute(attrs)
+
values.eachWithIndex {val, idx ->
def it = new Expando()
it.radio = new StringBuilder("<input type=\"radio\" name=\"${name}\" ")
@@ -61,6 +61,14 @@ class FormTagLibTests extends AbstractGrailsTagTests {
assertOutputEquals('<input type="text" name="testField" value="foo &gt; &quot; &amp; &lt; \'" id="testField" />', template, [value:/foo > " & < '/])
}
+ void testTextFieldTagWithRequired() {
+ def template = '<g:textField name="testField" value="${value}" required="false"/>'
+ assertOutputEquals('<input type="text" name="testField" value="foo &gt; &quot; &amp; &lt; \'" id="testField" />', template, [value:/foo > " & < '/])
+
+ template = '<g:textField name="testField" value="${value}" required="true"/>'
+ assertOutputEquals('<input type="text" name="testField" value="foo &gt; &quot; &amp; &lt; \'" id="testField" required="true" />', template, [value:/foo > " & < '/])
+ }
+
void testTextAreaWithBody() {
def template = '<g:textArea name="test">This is content</g:textArea>'
assertOutputEquals '<textarea name="test" id="test" >This is content</textarea>', template

0 comments on commit 484a933

Please sign in to comment.