HTML5 Form Validation – Why no one uses it, and how you can!



HTML5 Form Validation – Why no one uses it, and how you can!

0 0


talk-wip

Place for me to hold a WIP talk.

On Github tjvantoll / talk-wip

HTML5 Form Validation

Why no one uses it, and how you can!

TJ VanToll | @tjvantoll

- My name is TJ VanToll I work for Telerik (poll room) - We're a software development company, and we specialize in UI tools. Kendo UI? - So I work on Kendo UI - I'm also a member of the jQuery UI team

Forms are hard

Traditional form validation is hard

document.getElementById( "myForm" )
    .addEventListener( "submit", function( event ) {
        if ( document.getElementById( "myInput" ).value == "" ) {
            event.preventDefault();
            // Show some questionably UX and a11y
            // friendly error message.
        }
    });
});

HTML5 form validation is totally cool

<form>
    <input required>
    <button>Submit</button>
</form>
	
Submit
- I find most conference talks are about things you can't use or things that aren't applicable. - Form validation is practical - Everyone does it - Poll the room

Native Form Validation: A quick history

“No one uses HTML5 form validation”

-Me

What I want

Reality

Why does no one use it?

Problems:

Browser support is weird setCustomValidity() is an odd API Customizing error messages is hard Aggregating error messages is hard The :invalid pseudo-class is tricky to use You cannot style the bubbles

Problem #1: Browser support is weird

http://caniuse.com/#feat=form-validation - IE 6–9 have zero support for HTML5 form validation.

The curious case of Benjamin Button constraint validation on Safari, iOS Safari, and the Android browser.

Safari/iOS Safari/Android Browser let this submit empty

<form>
    <input required>
    <button>Submit</button>
</form>
	
Submit

Two scenarios to account for

  • Old IE
  • Safari / iOS Safari / Android Browser

Client-side validation is no substitute for server-side validation

		curl --data "param1=DELETE * FROM *" http://foo.com/bar.do
	

Your server is your fallback

Example

Problem #2: setCustomValidity() is an odd API

Example 1

Problem #3: Customizing error messages is hard

Customizing messages

<form>
    <input required type="email" id="baz">
    <button>Go</button>
</form>
<script>
    var baz = document.querySelector( "#baz" );
    function setErrorMessage() {
        if ( baz.validity.valueMissing ) {
            baz.setCustomValidity( "Email is required" );
        } else if ( baz.validity.typeMismatch ) {
            baz.setCustomValidity( "Please provide a valid email address" );
        } else {
            baz.setCustomValidity( "" );
        }
    };
    setErrorMessage();
    baz.addEventListener( "change", setErrorMessage );
</script>
Go

x-moz-errormessage

<form>
    <input required x-moz-errormessage="INVALID!">
    <button>Go</button>
</form>
Go

W3C Bug #10923: Add an attribute to override UI's validation message

title attribute

<form>
    <input pattern="[0-9]{5}" title="Enter 5 numbers">
    <button>Go</button>
</form>
Go

Problem #4: Aggregating error messages is hard

There is no way to determine when the user attempted to submit a form.

<form id="foo">
    <input required>
    <button>Go</button>
    <script>
        document.querySelector( "#foo" )
            .addEventListener( "submit", function() {
                alert( "hi!" );
            });
    </script>
</form>
	
Go

Aggregating Messages

Demo

Coming soon: invalid event on <form> elements!

Problem #5: The :invalid pseudo-class is tricky to use

:invalid applies immediately!

<form>
    <input type="text" id="foo" required>
</form>
<style>
    #foo:invalid { background: red; }
</style>

:moz-ui-invalid

Only match after interaction or attempted submission (full algorithm).

<form>
    <input type="text" id="bar" required>
    <button>Go</button>
</form>
<style>
    #bar:-moz-ui-invalid { background: red; }
</style>
Go

CSS Selectors Level 4 Spec

Only use :invalid after interaction

Demo

Problem #6: You cannot style the bubbles

Bubbles!

Old WebKit Hooks

WebKit used to have these pseudo-elements.

  • ::-webkit-validation-bubble
  • ::-webkit-validation-bubble-arrow
  • ::-webkit-validation-bubble-arrow-clipper
  • ::-webkit-validation-bubble-heading
  • ::-webkit-validation-bubble-message
  • ::-webkit-validation-bubble-text-block

You used to be able to do this

Styling the Bubbles

Chrome 28 removed the pseudo-elements for styling form validation messages.

Turning the bubbles off

<form>
    <input required id="field-x">
    <button>Go</button>
</form>
<script>
    document.getElementById( "field-x" )
        .addEventListener( "invalid", function( event ) {
            event.preventDefault();
        });
</script>
Go

Turning the bubbles off (for a whole form)

<form id="form-x">
    <input required>
    <button>Go</button>
</form>
<script>
    document.getElementById( "form-x" )
        .addEventListener( "invalid", function( event ) {
            event.preventDefault();
        }, true );
</script>
Go

Building your own bubbles

Demo

Problems:

Browser support is weird setCustomValidity() is an odd API Customizing error messages is hard Aggregating error messages is hard The :invalid pseudo-class is tricky to use You cannot style the bubbles

Production usage: your options

Server-side fallback only Polyfill Use a library based on HTML5

Option #1: Server-side fallback only

Demo

Option #2: Polyfill

Webshims

Demo

Webshims configuration

See http://afarkas.github.io/webshim/demos/

Option #3: Use a library based on HTML5

jQuery validation plugin

Kendo UI Validator

Production usage: your options

Server-side fallback only Polyfill Use a library based on HTML5

<shameless-plug>

Use code jqchtwcf for 43% off

http://manning.com/vantoll

</shameless-plug>

Thanks

TJ VanToll / @tjvantoll