Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Making Sure Your Forms Don't Suck

Making Sure Your Forms Don't Suck

94c767fbe5e2ce7ba74e9833c8e03d45?s=128

Damian Nicholson

October 23, 2017
Tweet

Transcript

  1. MAKING SURE YOUR FORMS DON'T SUCK @damian

  2. None
  3. None
  4. None
  5. ACCURATE FASTER CONFIDENT SATISFIED https://alistapart.com/article/inline-validation-in-web-forms

  6. https://baymard.com/blog/inline-form-validation E-Commerce sites containing client side validation 40% 60%

  7. https://baymard.com/blog/inline-form-validation E-Commerce sites containing client side validation 12% 40% 48%

  8. THIS LEADS ME TO BELIEVE IT'S PURELY AN IMPLEMENTATION ISSUE

  9. None
  10. None
  11. None
  12. None
  13. WHY IS IT SO HARD TO DO RIGHT?

  14. BUILT TO BE UNRELIABLE

  15. BUILT TO COMPLEMENT SERVER SIDE VALIDATION

  16. ALIGN* AND SYNCHRONISE VALIDATIONS DECLARED ON THE SERVER

  17. RECONCILE SERVER GENERATED VALIDATIONS WITH THOSE ON THE CLIENT

  18. onKeypress - onChange - onBlur RECONCILE ERRORS MANIFESTED ACROSS DIFFERENT

    EVENT PHASES
  19. CONDITIONAL VALIDATIONS DEPENDANT ON OTHER FIELD VALUES

  20. ASYNCHRONOUS VALIDATION

  21. HOW DO WE FIX IT?

  22. JUST BEING AWARE THAT SERVER SIDE VALIDATIONS EXIST

  23. RECONCILE ERRORS MANIFESTED ACROSS DIFFERENT EVENT PHASES onKeypress - onChange

    - onBlur
  24. onKeypress - onChange - onBlur RECONCILE ERRORS MANIFESTED ACROSS DIFFERENT

    EVENT PHASES
  25. REACT CONCEPT OF INTERNAL STATE MANAGEMENT MAKES MORE SENSE AND

    IS EASIER TO MANAGE
  26. const fieldAlias = 'userLogin'; this.setState({ [fieldAlias]: { ...this.state[fieldAlias], value: changeFn('hi@damiannicholson.com'),

    touched: true, } }, () => { Promise.all(validations.map((fn) => { return fn(this.state.values, this.serverErrors(), fieldAlias, 'onChange'); })) .then(() => { this.setValid() }) .catch((errors) => { this.setInvalid(errors) }); });
  27. REMOVE 1 to 1 MAPPING BETWEEN FIELD VALUES AND VALIDATIONS

  28. const validationFn = (values, serverErrors = {}, fieldUpdated, eventPhase) {

    return new Promise((resolve, reject) => { const errors = {}; if (!values.userLogin) { errors.userLogin = 'Please enter your email address'; } Object.assign(errors, serverErrors); if (Object.keys(errors).length === 0) { return resolve(errors); } return reject(errors); }); }; CONDITIONAL VALIDATIONS DEPENDANT ON OTHER FIELDS
  29. const SignInForm = ({ ...props }) => { const {

    handleChange, handleBlur, form, method, fields, ...other } = props; const { userLogin, password } = form; return ( <form method={method} action="POST" {...other}> <input type="text" data-alias="userLogin" onChange={handleChange} onBlur={handleBlur} value={userLogin.value} /> {userLogin.touched && userLogin.errors.length > 0 && <span>{userLogin.errors}</span> } ... <button>Sign in</button> </form> ); }; export default conferizeForm(SignInForm, validationFn);
  30. Consolidated event handling - either onChange or onBlur Conditional validations

    Sync and async validations declared and resolved using Promise API Composable validations Developers own their form and it's fields Synchronising server and client side validations
  31. MAKES USERS HAPPY BUT ONLY IF DONE RIGHT

  32. REACT MAKES THAT A LOT EASIER

  33. THE END