A space to discuss online store customization, theme development, and Liquid templating.
We do need the abilitiy to use both, the create_customer and customer_login form on the same page.
When doing so, logging in and creating new accounts works well. However, we do experience some bugs:
{{ 'login-register.css' | asset_url | stylesheet_tag }} <div class="row login-register-wrapper" data-state="init"> <div class="login-form-container"> {% form 'customer_login' %} {% if form.errors %} <div class="form-notification error"> {{ form.errors | default_errors }} </div> {% endif %} <input data-return-to type="hidden" name="return_to" value="/account"> <h4>{{ 'customer.login_page.login' | t }}</h4> <div class="field" data-valid="true"> <input type="email" data-cs-mask name="customer[email]" class="full {% if form.errors contains 'form' %}invalid{% endif %}" value="" autocomplete="email" autocorrect="off" autocapitalize="off" placeholder="{{ 'customer.login_page.email' | t }}" > <label for="customer_email">{{ 'customer.login_page.email' | t }}</label> <span class="field-error-message" data-for="customer[email]"> {% render 'svg-icons' with 'error' %} {{ 'customer.form_error_messages.email' | t }} </span> </div> <div class="field" data-valid="true"> <input data-cs-mask type="password" name="customer[password]" class="full {% if form.errors contains 'form' %}invalid{% endif %}" value="" placeholder="{{ 'customer.login_page.password' | t }}" > <label for="customer_password">{{ 'customer.login_page.password' | t }}</label> <span class="field-error-message" data-for="customer[password]"> {% render 'svg-icons' with 'error' %} {{ 'customer.form_error_messages.password' | t }} </span> </div> <div class="field"> <button type="button" data-validate-button class="button full"> <span>{{ 'customer.login_page.sign_in' | t }}</span> </button> </div> <div class="login-recover"> <a class="text-button" href="#reset" onclick="switchState('reset')"> {{- 'customer.login_page.forgot_password' | t -}} </a> </div> {% endform %} </div> <div class="register-form-container"> {% form 'create_customer' %} {{ form.posted_successfully? | json }} {% if form.errors %} <div class="form-notification error"> {{ form.errors | default_errors }} </div> {% endif %} <input data-return-to type="hidden" name="return_to" value="/account"> <h4>{{ 'customer.login_page.create_account' | t }}</h4> <p>{{ 'customer.login_page.create_account_description' | t }}</p> {% for i in (1..3) %} <div class="register-form-usp"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M8.90909 15.7836L5.53137 12.391C5.1568 12.0148 4.54775 12.0148 4.17317 12.391C3.80091 12.7649 3.80091 13.3694 4.17317 13.7433L8.20044 17.7882C8.59131 18.1808 9.22687 18.1808 9.61774 17.7882L19.8268 7.53434C20.1991 7.16044 20.1991 6.55597 19.8268 6.18208C19.4523 5.80586 18.8432 5.80586 18.4686 6.18208L8.90909 15.7836Z" fill="#00AC4F"/> </svg> {% assign translate_str = 'customer.login_page.create_account_benefit_' | append: i %} <span>{{ translate_str | t }}</span> </div> {% endfor %} <div class="register-form-fields" id="recover"> <div class="fields"> <div class="field" data-valid="true"> <input type="text" data-cs-mask name="customer[first_name]" class="full" value="{% if form.first_name %}{{ form.first_name }}{% endif %}" placeholder="{{ 'customer.login_page.first_name' | t }}" required > <label for="first_name">{{ 'customer.login_page.first_name' | t }}</label> <span class="field-error-message" data-for="customer[first_name]"> {% render 'svg-icons' with 'error' %} {{ 'customer.form_error_messages.first_name' | t }} </span> </div> <div class="field" data-valid="true"> <input type="text" data-cs-mask name="customer[last_name]" class="full" value="{% if form.last_name %}{{ form.last_name }}{% endif %}" placeholder="{{ 'customer.login_page.last_name' | t }}" > <label for="last_name">{{ 'customer.login_page.last_name' | t }}</label> <span class="field-error-message" data-for="customer[last_name]"> {% render 'svg-icons' with 'error' %} {{ 'customer.form_error_messages.last_name' | t }} </span> </div> </div> <div class="fields"> <div class="field"> <input data-birthday-input onKeyDown="evaluateBirthday(event);" onChange="submitBirthdayChange(event);" type="text" minlength="10" maxlength="10" data-cs-mask name="" class="full" placeholder="{{ 'customer.login_page.birthday' | t }}" id="visual-birthday-input" > <label for="visual-birthday-input">{{ 'customer.login_page.birthday' | t }}</label> <script> function evaluateBirthday(event) { const target = event.target; const targetValLength = target.value.length; const allowedCharList = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.']; if (!allowedCharList.includes(event.key)) { if (event.key !== 'Backspace') { event.preventDefault(); } return; } if (targetValLength == 1 || targetValLength == 4) { setTimeout(() => { target.value = target.value + '.'; }, 50); } if (targetValLength == 9) { console.log(target.value); } } function getAge(birthDate) { var today = new Date(); var age = today.getFullYear() - birthDate.getFullYear(); var m = today.getMonth() - birthDate.getMonth(); if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) { age--; } return age; } function submitBirthdayChange(event) { const submitButton = document.querySelector("button[type='submit'].button"); const dateStr = event.target.value; try { console.log(dateStr); const dateStrSplit = dateStr.split('.'); var dateBirthdayDate = dateStrSplit[2] + '-' + dateStrSplit[1] + '-' + dateStrSplit[0]; document.querySelector('[data-birthday-date]').value = dateBirthdayDate; console.log(dateBirthdayDate); const dateBirthdayDateObj = new Date(); dateBirthdayDateObj.setYear(parseInt(dateStrSplit[2])); dateBirthdayDateObj.setMonth(parseInt(dateStrSplit[1]) - 1); dateBirthdayDateObj.setDate(parseInt(dateStrSplit[0])); const userAge = getAge(dateBirthdayDateObj); if (userAge < 16) { alert('Leider musst du mindestens 16 Jahre alt sein um dich anmelden zu dürfen. Sorry'); submitButton.setAttribute('disabled', true); } else { submitButton.removeAttribute('disabled'); } } catch (e) { console.log('Invalid date input: ' + dateStr); console.log(e.stack); } } </script> </div> </div> <div class="field" data-valid="true"> <input type="email" data-cs-mask name="customer[email]" class="full {% if form.errors contains 'email' %}invalid{% endif %}" value="" placeholder="{{ 'customer.login_page.email' | t }}" > <label for="email">{{ 'customer.login_page.email' | t }}</label> <span class="field-error-message" data-for="customer[email]"> {% render 'svg-icons' with 'error' %} {{ 'customer.form_error_messages.email' | t }} </span> </div> {% comment %}Move this input outside of the div to ensure that all CSS is working properly {% endcomment %} <input hidden type="date" data-birthday-date data-cs-mask name="customer[note]" class="full" placeholder="{{ 'customer.login_page.birthday' | t }}" > <div class="field" data-valid="true"> <input type="password" data-cs-mask name="customer[password]" class="full" value="" placeholder="{{ 'customer.login_page.password' | t }}" > <label for="password">{{ 'customer.login_page.password' | t }}</label> <span class="field-error-message" data-for="customer[password]"> {% render 'svg-icons' with 'error' %} {{ 'customer.form_error_messages.password' | t }} </span> </div> <div class="field marketing-field"> <input id="marketing" type="checkbox" data-cs-mask name="customer[accepts_marketing]" class="full" > <label for="marketing"> {{- 'customer.login_page.marketing' | t | replace: '%d', "<a href='/policies/privacy-policy'>Datenschutzerklärung</a>" -}} </label> </div> <button type="button" data-validate-button class="button full"> <span>{{ 'customer.login_page.submit_register' | t }}</span> </button> </div> {% endform %} </div> <div class="reset-password-form-container"> <h4>{{ 'customer.recover_password.title' | t }}</h4> <p>{{ 'customer.recover_password.subtext' | t }}</p> {%- form 'recover_customer_password', return_to: '/account/login#reset-confirmation' -%} {%- if form.errors -%} <div class="form-notification error" id="RecoverEmail-email-error"> {% render 'svg-icons' with 'thb-error' %} {{ form.errors.messages.form }} </div> {%- endif -%} <div class="field"> <input type="email" value="" name="email" id="RecoverEmail" data-cs-mask autocorrect="off" autocapitalize="off" autocomplete="email" placeholder="{{ 'customer.login_page.email' | t | escape }}" {% if form.errors %} aria-invalid="true" aria-describedby="RecoverEmail-email-error" autofocus {% endif %} class="full" placeholder="{{ 'customer.login_page.email' | t }}" > <label for="RecoverEmail"> {{ 'customer.login_page.email' | t }} </label> </div> <button type="button" data-validate-button class="button full"> <span>{{ 'customer.login_page.submit' | t | escape }}</span> </button> {%- endform -%} </div> <div class="reset-password-confirmation"> <h4>{{ 'customer.recover_password.success_title' | t }}</h4> <p>{{ 'customer.recover_password.success' | t }}</p> <a class="button full">{{ 'customer.login_page.sign_in' | t }}</a> <p></p> </div> </div> <div class="row"> <div class="guest-form-container" data-show="false"> <div class="guest-form-content"> <h4>{{ 'customer.login_page.guest_order' | t }}</h4> <p>{{ 'customer.login_page.guest_order_description' | t }}</p> </div> <form action="{{ routes.cart_url }}" method="post" novalidate> <button type="submit" class="button white medium" name="checkout" title="{{ 'customer.login_page.guest_order_submit' | t }}" > <span>{{ 'customer.login_page.guest_order_submit' | t }}</span> </button> </form> </div> <script> function showGuestCheckout() { const url = new URL(window.location.href); if (url.searchParams.has('show-guest-checkout')) { document.querySelector('.guest-form-container').setAttribute('data-show', true); document.querySelectorAll('[data-return-to]').forEach((item) => { item.value = '/checkout'; }); } } showGuestCheckout(); function switchState(newState) { document.querySelector('.login-register-wrapper').setAttribute('data-state', newState); } if (window.location.hash !== '') { switchState(window.location.hash.replace('#', '')); } function validateInput(input) { const field = input.closest(".field"); if(!input.value || input.value === "") { field.setAttribute("data-valid", false); return false; } else { field.setAttribute("data-valid", true); return true; } } document.querySelectorAll(".field[data-valid] input").forEach(input => { input.addEventListener("change", () => { validateInput(input); }) }) document.querySelectorAll('[data-validate-button]').forEach((button) => { button.addEventListener("click", () => { const form = button.closest("form"); console.log(form); let allInputsValid = true; form.querySelectorAll(".field[data-valid] input").forEach(input => { if(!validateInput(input)) { allInputsValid = false; } }); if(allInputsValid) { form.submit(); } }) }); </script> </div> {% schema %} { "name": "Main Login Register", "settings": [ { "type": "color", "id": "background_color", "label": "Background Color", "default": "{{ shop.brand.colors.primary[0].foreground }}" } ] } {% endschema %}