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 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 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
Commit_comment_tip

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.