input-validator.ts 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import { materialIcon } from '@/features/utils/material-icon'
  2. export default function inputValidator(
  3. inputEl: HTMLInputElement | HTMLTextAreaElement
  4. ) {
  5. const messageEl = document.createElement('div')
  6. messageEl.className =
  7. inputEl.getAttribute('data-ol-validation-message-classes') ||
  8. 'small text-danger mt-2 form-text'
  9. messageEl.hidden = true
  10. const messageInnerEl = messageEl.appendChild(document.createElement('span'))
  11. messageInnerEl.className = 'form-text-inner'
  12. const messageTextNode = document.createTextNode('')
  13. const iconEl = materialIcon('error')
  14. messageInnerEl.append(iconEl)
  15. messageInnerEl.append(messageTextNode)
  16. inputEl.insertAdjacentElement('afterend', messageEl)
  17. // Hide messages until the user leaves the input field or submits the form.
  18. let canDisplayErrorMessages = false
  19. // Handle all kinds of inputs.
  20. inputEl.addEventListener('input', handleUpdate)
  21. inputEl.addEventListener('change', handleUpdate)
  22. // The user has left the input field.
  23. inputEl.addEventListener('blur', displayValidationMessages)
  24. // The user has submitted the form and the current field has errors.
  25. inputEl.addEventListener('invalid', (e: Event) => {
  26. // Block the display of browser error messages.
  27. e.preventDefault()
  28. // Force the display of messages.
  29. inputEl.setAttribute('data-ol-dirty', '')
  30. displayValidationMessages()
  31. })
  32. function handleUpdate() {
  33. // Mark an input as "dirty": the user has typed something in at some point
  34. inputEl.setAttribute('data-ol-dirty', '')
  35. // Provide live updates to content sensitive error message like this:
  36. // Please include an '@' in the email address. 'foo' is missing an '@'.
  37. // We should not leave a stale message as the user types.
  38. updateValidationMessageContent()
  39. }
  40. function displayValidationMessages() {
  41. // Display all the error messages and highlight fields with red border.
  42. canDisplayErrorMessages = true
  43. updateValidationMessageContent()
  44. }
  45. function updateValidationMessageContent() {
  46. if (!canDisplayErrorMessages) return
  47. if (!inputEl.hasAttribute('data-ol-dirty')) return
  48. if (inputEl.validity.valid) {
  49. messageEl.hidden = true
  50. // Require another blur before displaying errors again.
  51. canDisplayErrorMessages = false
  52. } else {
  53. messageTextNode.data = inputEl.validationMessage
  54. messageEl.hidden = false
  55. }
  56. }
  57. }