Purpose#
Register is the reusable that renders and handles storefront user-registration flows.It validates registration inputs and coordinates registration submission/feedback behavior.Where it's rendered#
It’s rendered in multiple places:Components/Register/Default.liquid
Reusables/LoginModal/Default.liquid
From Components/Register/Default.liquid:{% render 'Reusables\\Register\\Default', uniquekey: uniquekey %}
Liquid parameters#
Used to make DOM ids/names unique.
The template appends it to all field id/name attributes.
Model shape (storefront example)#
Sanitized real storefront example (provided by the user) of the component/page model that renders registration:{
"name": "Register",
"view": "Default",
"section": "SectionA",
"settings": {
"retypePassword": false,
"id": "Component Id",
"section": "SectionA",
"type": "Register",
"name": "Register",
"configuredInContentApi": false,
"view": "Default",
"displayName": "",
"cssClass": "",
"header": "",
"alignment": "Left"
},
"translations": {
"registerAccount": "Sample text",
"alreadyAccount": "Sample text",
"login": "Sample text"
}
}
The reusable itself relies mostly on Reusables.Register.Translations.* and does not read the page translations object directly.
Registration is feature-gated by GlobalData.Settings.showRegistration inside the reusable template.
Template behavior (Liquid + Alpine)#
Feature flag#
The form is rendered only when:GlobalData.Settings.showRegistration is truthy.
Alpine wiring#
Alpine component: x-data="registerreusabledefault"
@submit.prevent="checkForm(uniquekey, successMessage, errorMessageFail, errorMessageUserExists)"
Fields#
All fields are required unless stated otherwise:First name (register-firstname-<uniquekey>) (required)
Last name (register-lastname-<uniquekey>) (required)
Email (register-email-<uniquekey>) (required, email format)
Password (register-password-<uniquekey>) (required, must pass weak-password rules)
Confirm password (register-confirm-password-<uniquekey>) (required, must match password)
Terms consent checkbox (register-terms-<uniquekey>) (required)
Password visibility#
Both password fields include a toggle checkbox that triggers toggleVisibility($event) to switch the input type between password and text.Data contract (JS runtime)#
Document runtime state shape, factories, and main state fields.JavaScript#
Global object#
File: Reusables/Register/Default.jsExposes: registerreusabledefaultinit#
Initializes field references and wires up validation handlers.If enterprise captcha is enabled (passed in via initComponent(...)), it may also initialize the captcha widget/observers.validateField#
Validates a single input and sets errors[field.name].Used on blur for most fields and on change for required checkboxes.toggleVisibility#
Toggles a password input between type="password" and type="text".Used by the password “eye” toggle checkbox in the template.Returns whether all tracked inputs are currently valid based on errors + required empties.Resets all form inputs and clears validation UI state.Also called when clearing modal forms via the clear-login-modal-forms event.Validates the form and submits registration via servicesreusabledefault.accountRegister(...).When enterprise captcha is enabled, it retrieves a captcha token (challenge or non-challenge mode) and includes it in the request headers.findResponseEl#
Helper used during captcha challenge mode.Finds the textarea[name='g-recaptcha-response'] element (scoped to the form when possible) so the JS can read token updates.getEnterpriseCaptchaToken#
Returns the captcha token that should accompany the registration request.Non-challenge mode: calls grecaptcha.enterprise.execute(siteKey, { action }).
Challenge mode: reads the widget response from the hidden g-recaptcha-response textarea (or widget API when available).
initCaptchaChallenge#
Initializes captcha challenge mode behavior.Wires observers/listeners so the component can detect when the user completes (or expires) the checkbox challenge and keep captchaToken in sync.onTokenMaybeChanged#
Internal helper used by initCaptchaChallenge().Runs whenever the captcha response textarea potentially changes (mutation observer / events / click rechecks) and updates captchaToken + captchaError state.recheck#
Internal helper used by the captcha challenge flow to re-read the token shortly after interactions (covers async widget updates).resetCaptcha#
Clears local captcha state and disconnects observers.Called after clearing forms (e.g. when closing the login modal) and when a fresh captcha verification is needed.set#
Internal helper used by initCaptchaChallenge().Hooks into the captcha response textarea’s .value setter so the component can react even when the widget updates the value without triggering standard DOM events.tick#
Internal helper used by initCaptchaChallenge().Runs a short, self-canceling polling loop to detect slow async fills of the captcha response.waitForGrecaptcha#
Internal helper used by initCaptchaChallenge().Waits (briefly) for window.grecaptcha to become available because the captcha script is loaded async/defer.Global Alpine stores#
add(message, icon, type, autoClose)
Services / API calls#
servicesreusabledefault.accountRegister(info)Request payload shape (as built by the JS):{
"FirstName": "Sample text",
"LastName": "Sample text",
"Email": "sample@example.com",
"Password": "Sample text",
"ValidatePassword": "Sample text"
}
Dependencies#
Liquid: Reusables/Register/Default.liquid
JS: Reusables/Register/Default.js
Translations: Reusables/Register/Default.json
Components/Register/Default.liquid
Reusables/LoginModal/Default.liquid
servicesreusabledefault.accountRegister(...)
Notes#
The template uses uniquekey to avoid DOM id collisions when the same form appears more than once (e.g. inside the login modal).
The password rules are enforced client-side; backend should enforce the same (or stricter) policy.
The form is gated by GlobalData.Settings.showRegistration; when disabled, this reusable renders nothing.
Modified at 2026-06-15 06:55:43