Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

support form html5's required attribute #112

Open
wants to merge 1 commit into from

4 participants

Stefan Armbruster Jeff Scott Brown Rob Fletcher Denis Falqueto
Stefan Armbruster

html5 supports usage of a 'required' attribute to indicate mandatory fields.
Previously it was odd behaviour because 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

Stefan Armbruster sarmbruster 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
484a933
Jeff Scott Brown
Owner

Stefan,

Would you mind creating a JIRA describing the issue related to this commit?

Thanks for the help.

Rob Fletcher
Collaborator

The same behaviour is true of all boolean attributes in HTML5. e.g. readonly, disabled, multiple, etc. Using false as a value for any such attribute is misleading as the presence of the attribute indicates true. Boolean attributes should really be handled one of 3 ways:

  • A simple SGML-style attribute, i.e. with no ="value". This would be incompatible with any code that handles markup as XML compliant, probably including Groovy's MarkupBuilder.
  • XHTML-style where the value is the name of the property, e.g. `readonly="readonly". I personally find this really ugly but it is valid and arguably the least confusing option.
  • Using the empty string as a value, e.g. readonly="". This remains XML compliant and is less unnecessarily verbose than repeating the attribute name however, I know some people have found it confusing.
Denis Falqueto

@robfletcher I disagree. Those attributes are really dumbly defined (for God's sake, why not just put a true/false or yes/no on the specs?), but we could (and should) do the right thing in Grails. Let's use that as a true boolean value, which is the real purpose for that kind of attribute.

I've done a similar pull request for that kind of behavior just now: #159 (and its backport for 2.0.x: #160). You can see that the result is very usefull.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Oct 03, 2011
Stefan Armbruster sarmbruster 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
484a933
This page is out of date. Refresh to see the latest.
20 grails-plugin-gsp/src/main/groovy/org/codehaus/groovy/grails/plugins/web/taglib/FormTagLib.groovy
@@ -117,6 +117,7 @@ class FormTagLib {
117 117
118 118 def fieldImpl(out, attrs) {
119 119 resolveAttributes(attrs)
  120 + handleRequiredAttribute(attrs)
120 121 attrs.id = attrs.id ?: attrs.name
121 122 out << "<input type=\"${attrs.remove('type')}\" "
122 123 outputAttributes(attrs, out)
@@ -155,6 +156,8 @@ class FormTagLib {
155 156
156 157 if (checked instanceof String) checked = Boolean.valueOf(checked)
157 158
  159 + handleRequiredAttribute(attrs)
  160 +
158 161 if (value == null) value = false
159 162
160 163 out << "<input type=\"hidden\" name=\"_${name}\" /><input type=\"checkbox\" name=\"${name}\" "
@@ -233,6 +236,18 @@ class FormTagLib {
233 236 }
234 237
235 238 /**
  239 + * handle HTML's 'required' attribute: only add it if it's value is true in HTML even 'required="false"' marks the field as required
  240 + * @param attrs
  241 + */
  242 + void handleRequiredAttribute(attrs) {
  243 + def requiredString = attrs.remove('required')
  244 + Boolean required = Boolean.valueOf(requiredString)
  245 + if (required) {
  246 + attrs.required = true
  247 + }
  248 + }
  249 +
  250 + /**
236 251 * Dump out attributes in HTML compliant fashion.
237 252 */
238 253 void outputAttributes(attrs, writer) {
@@ -759,6 +774,7 @@ class FormTagLib {
759 774 if (disabled && Boolean.valueOf(disabled)) {
760 775 attrs.disabled = 'disabled'
761 776 }
  777 + handleRequiredAttribute(attrs)
762 778
763 779 writer << "<select name=\"${attrs.remove('name')?.encodeAsHTML()}\" "
764 780 // process remaining attributes
@@ -900,6 +916,8 @@ class FormTagLib {
900 916 attrs.disabled = 'disabled'
901 917 }
902 918 def checked = attrs.remove('checked') ? true : false
  919 + handleRequiredAttribute(attrs)
  920 +
903 921 out << "<input type=\"radio\" name=\"${name}\"${ checked ? ' checked="checked" ' : ' '}value=\"${value?.toString()?.encodeAsHTML()}\" "
904 922 // process remaining attributes
905 923 outputAttributes(attrs, out)
@@ -921,6 +939,8 @@ class FormTagLib {
921 939 def values = attrs.remove('values')
922 940 def labels = attrs.remove('labels')
923 941 def name = attrs.remove('name')
  942 + handleRequiredAttribute(attrs)
  943 +
924 944 values.eachWithIndex {val, idx ->
925 945 def it = new Expando()
926 946 it.radio = new StringBuilder("<input type=\"radio\" name=\"${name}\" ")
8 grails-test-suite-web/src/test/groovy/org/codehaus/groovy/grails/web/taglib/FormTagLibTests.groovy
@@ -61,6 +61,14 @@ class FormTagLibTests extends AbstractGrailsTagTests {
61 61 assertOutputEquals('<input type="text" name="testField" value="foo &gt; &quot; &amp; &lt; \'" id="testField" />', template, [value:/foo > " & < '/])
62 62 }
63 63
  64 + void testTextFieldTagWithRequired() {
  65 + def template = '<g:textField name="testField" value="${value}" required="false"/>'
  66 + assertOutputEquals('<input type="text" name="testField" value="foo &gt; &quot; &amp; &lt; \'" id="testField" />', template, [value:/foo > " & < '/])
  67 +
  68 + template = '<g:textField name="testField" value="${value}" required="true"/>'
  69 + assertOutputEquals('<input type="text" name="testField" value="foo &gt; &quot; &amp; &lt; \'" id="testField" required="true" />', template, [value:/foo > " & < '/])
  70 + }
  71 +
64 72 void testTextAreaWithBody() {
65 73 def template = '<g:textArea name="test">This is content</g:textArea>'
66 74 assertOutputEquals '<textarea name="test" id="test" >This is content</textarea>', template

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.