Have your say in Community Polls: What was/is your greatest motivation to start your own business?
Our Partner & Developer boards on the community are moving to a brand new home: the .dev community forums! While you can still access past discussions here, for all your future app and storefront building questions, head over to the new forums.

Using a create_customer and customer_login form on the same page

Using a create_customer and customer_login form on the same page

KevinSchade
Shopify Partner
8 0 0

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:

User logs in with a wrong password:
The error message appears on both forms. Is there a way to check which form causes the errors?
 
User tries to create an account which already exists
Unfortunately, there is no error message at all. I assume that this happens because the error happens on the second form (register form) and not the first one.

My section code:
 
{{ '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 %}
Replies 0 (0)