diff --git a/services/web/app/views/_mixins/formMessages.pug b/services/web/app/views/_mixins/formMessages.pug index 01845a2f59..a9531595cb 100644 --- a/services/web/app/views/_mixins/formMessages.pug +++ b/services/web/app/views/_mixins/formMessages.pug @@ -4,6 +4,12 @@ mixin formMessages() role="alert" ) +mixin formMessagesNewStyle() + div( + data-ol-form-messages-new-style='', + role="alert" + ) + mixin customFormMessage(key, kind) if kind === 'success' div.alert.alert-success( diff --git a/services/web/frontend/js/features/form-helpers/hydrate-form.js b/services/web/frontend/js/features/form-helpers/hydrate-form.js index 54d67dcafb..99c6c8160e 100644 --- a/services/web/frontend/js/features/form-helpers/hydrate-form.js +++ b/services/web/frontend/js/features/form-helpers/hydrate-form.js @@ -80,7 +80,10 @@ function formSubmitHelper(formEl) { // Let the user re-submit the form. formEl.dispatchEvent(new Event('idle')) } finally { + // call old and new notification builder functions + // but only one will be rendered showMessages(formEl, messageBag) + showMessagesNewStyle(formEl, messageBag) } }) } @@ -126,6 +129,8 @@ function hideFormElements(formEl) { } } +// TODO: remove the showMessages function after every form alerts are updated to use the new style +// TODO: rename showMessagesNewStyle to showMessages after the above is done function showMessages(formEl, messageBag) { const messagesEl = formEl.querySelector('[data-ol-form-messages]') if (!messagesEl) return @@ -192,6 +197,81 @@ function showMessages(formEl, messageBag) { }) } +function showMessagesNewStyle(formEl, messageBag) { + const messagesEl = formEl.querySelector('[data-ol-form-messages-new-style]') + if (!messagesEl) return + + // Clear content + messagesEl.textContent = '' + formEl.querySelectorAll('[data-ol-custom-form-message]').forEach(el => { + el.hidden = true + }) + + // Render messages + messageBag.forEach(message => { + const customErrorElements = message.key + ? formEl.querySelectorAll( + `[data-ol-custom-form-message="${message.key}"]` + ) + : [] + if (message.key && customErrorElements.length > 0) { + // Found at least one custom error element for key, show them + customErrorElements.forEach(el => { + el.hidden = false + }) + } else { + // No custom error element for key on page, append a new error message + const messageElContainer = document.createElement('div') + messageElContainer.className = classNames( + 'notification', + 'text-centered', + { + 'notification-type-error': message.type === 'error', + 'notification-type-success': message.type !== 'error', + } + ) + const messageEl = document.createElement('div') + + messageEl.className = 'notification-content' + messageEl.textContent = message.text || `Error: ${message.key}` + messageEl.setAttribute('aria-live', 'assertive') + messageEl.setAttribute( + 'role', + message.type === 'error' ? 'alert' : 'status' + ) + if (message.hints && message.hints.length) { + const listEl = document.createElement('ul') + message.hints.forEach(hint => { + const listItemEl = document.createElement('li') + listItemEl.textContent = hint + listEl.append(listItemEl) + }) + messageEl.append(listEl) + } + + messageElContainer.appendChild(messageEl) + messagesEl.append(messageElContainer) + } + if (message.key) { + // Hide the form elements on specific message types + const hideOnError = formEl.attributes['data-ol-hide-on-error'] + if ( + hideOnError && + hideOnError.value && + hideOnError.value.match(message.key) + ) { + hideFormElements(formEl) + } + // Hide any elements with specific `data-ol-hide-on-error-message` message + document + .querySelectorAll(`[data-ol-hide-on-error-message="${message.key}"]`) + .forEach(el => { + el.hidden = true + }) + } + }) +} + export function inflightHelper(el) { const disabledInflight = el.querySelectorAll('[data-ol-disabled-inflight]') const showWhenNotInflight = el.querySelectorAll('[data-ol-inflight="idle"]')