Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

support form html5's required attribute #112

Closed
wants to merge 1 commit into from

5 participants

@sarmbruster

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

@sarmbruster 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
@jeffbrown
Owner

Stefan,

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

Thanks for the help.

@robfletcher
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.
@denisfalqueto

@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.

@lhotari
Collaborator

Closing outdated pull requests.

@lhotari lhotari closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Oct 3, 2011
  1. @sarmbruster

    support form html5's required attribute

    sarmbruster authored
    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
This page is out of date. Refresh to see the latest.
View
20 ...lugin-gsp/src/main/groovy/org/codehaus/groovy/grails/plugins/web/taglib/FormTagLib.groovy
@@ -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}\" ")
View
8 ...st-suite-web/src/test/groovy/org/codehaus/groovy/grails/web/taglib/FormTagLibTests.groovy
@@ -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
Something went wrong with that request. Please try again.