Conditional field visibility fix

User
<style>
.hub-multistep-btn {
  background-color: #00b4d5;
  border-radius: 25px;
  font-weight: 600;
  min-height: 40px;
  cursor: pointer;
  width: 100%;
  font-size: 15px;
  text-align: center;
  transition: all .3s;
  fill: #fff;
}

#step-progress {
  margin: 20px 0;
  text-align: center;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.step-indicator {
  display: inline-block;
  width: 30px;
  height: 30px;
  line-height: 30px;
  border-radius: 50%;
  margin: 0 5px;
  font-size: 10px;
  font-weight: 600;
  position: relative;
  text-align: center;
  border: 1px solid #000221;
  color: #000221;
}

.step-indicator.active {
  background-color: #00b4d5 !important;
  border-color: #00b4d5 !important;
  color: #a8eeff;
}

.step-head-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  position: relative;
}
.steps-container {
  display: flex;
  position: relative;
}
.steps-container:not(:last-child)::after {
    content: '';
    position: absolute;
    top: 15px;
    left: 80%;
    right: -270%;
    height: 1px;
    background-color: #babfc5;
    z-index: 0;
}
.step-head-container.completed .step-indicator {
  background-color: #000221 !important;
  border: 1px solid #5fdb3a;
  color: #fafafa;
}
.hs_test___letzte_konversion__asset_tag_ {
  display: none !important;
}
span.hs-form-required {
  padding-left: 5px;
  color: #9b0077;
}
.hs-form-field input:not([type=checkbox]), .hs-form-field select, .hs-input.hs-fieldtype-textarea {
  color: #000221;
  font-size: 18px;
  height: 45px;
  transition: border-bottom .2s ease-in-out, background-color .2s ease-in-out, color .2s ease-in-out;
  width: 100% !important;
  background-color: #fff ;
  border: 1px solid #ccccd3;
  border-radius: 6px !important;
  padding: 10px;
}
.hs_hs_language {
  display: none !important;
}
.hs-form-private fieldset {
  margin-bottom: 0 !important;
}
.step-buttons {
  margin-top: 30px;
  text-align: center;
  display: flex;
  gap: 12px;
}
.step-head-container.completed .step-indicator {
  background-color: #000221 !important;
  border: 1px solid #5fdb3a;
  color: #fafafa;
}
.step-buttons button {
  background-color: #00b4d5;
  border: 1px solid #00b4d5;
  border-radius: 25px;
  font-weight: 600;
  min-height: 40px;
  cursor: pointer;
  width: 100%;
  font-size: 15px;
  text-align: center;
  transition: all .3s;
  fill: #fff;
  color: #fff;
  flex: 1;
}
.step-buttons button#nextBtn:hover {
  background-color: #0092ad !important;
  color: #fff !important;
}
.step-buttons button#backBtn {
  background-color: #fff;
  color: #00b4d5;
  border: 1px solid #00b4d5;
}
.step-buttons button#backBtn:hover {
  background-color: #00b4d5;
  color: #fff;
}
.hs-form-field {
  margin-bottom: 20px;
}
.input-error {
  border-color: red !important;
}
.hs-error-msgs {
  display: block !important;
  color: red;
  font-size: 14px;
  margin-top: 4px;
}
.hs-input[type=checkbox] {
  appearance: none;
  background-color: #fff ;
  border: 1px solid #717e86;
  border-radius: 4px;
  cursor: pointer;
  height: 30px;
  width: 30px !important;
  transition: background-color .2s ease, border .5s ease;
}
.hs-input[type=checkbox]:checked {
  background-color: #00b4d5 !important;
}
.hs-input[type=checkbox]:checked:after {
  background-color: #00b4d5;
  border-radius: 50%;
  color: #fff;
  content: "✓";
  display: flex;
  border: 1px solid #fff;
  font-size: 11px;
  justify-content: center;
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 16px;
  height: 18px;
}
.hs_welche_produkte_wollen_sie_live_sehen_ label > span:first-child {
  font-size: 14px;
  font-weight: 500;
  line-height: 30px;
  text-align: left;
  color: #33354d;
}
.hs_submit.hs-submit {
  width: 100%;
  display: flex;
  gap: 12px;
  justify-content: center;
  margin-top: 30px;
}
input.hs-button.primary.large {
  width: 100%;
  padding: 0;
}
input:focus, textarea:focus, select:focus {
  background-color: #eaf8fc !important;
  border: 1px solid #00b4d5;
  box-shadow: none !important;
  color: #000221;
  outline: none !important;
}
.hs-form-private ul li {
  margin-block: 10px;
}
.hs-form-booleancheckbox label, .hs-form-checkbox label {
  align-items: center;
}
.hs-submit button#backBtn {
    background-color: #fff;
    color: #00b4d5;
    border: 1px solid #00b4d5;
    border-radius: 25px;
    font-weight: 600;
    min-height: 40px;
    width: 100%;
    font-size: 15px;
    text-align: center;
    transition: all .3s;
    fill: #fff;
}
.hs_submit .actions {
    width: 100%;
}
span.step-label {
    font-size: 12px;
    font-weight: 700;
}
</style>
<script>

</script>
<script>
hbspt.forms.create({
  portalId: "6868748",
  formId: "7e1746ed-1467-45f2-b011-d8edae5509a5",
  target: "#hubspot-form-2",
  onFormReady: function () {
    const waitForFields = setInterval(() => {
      const form = document.querySelector('#hubspot-form-2 form');
      const allFields = form?.querySelectorAll('.hs-form-field');
      if (!form || !allFields || allFields.length < 5) return;

      clearInterval(waitForFields);

      const stepFields = {
        0: ['welche_produkte_wollen_sie_live_sehen_','bereits_sap_business_bydesign_kunde_'],
        1: ['message'],
        2: []
      };

      allFields.forEach(field => {
        const input = field.querySelector('input, select, textarea');
        if (input && input.name && !Object.values(stepFields).flat().includes(input.name)) {
          stepFields[2].push(input.name);
        }
      });

      const stepProgress = document.createElement('div');
      stepProgress.innerHTML = `
        <div id="step-progress">
          <div class="steps-container">
            <div class="step-head-container">
              <div class="step-indicator active">1</div>
              <span class="step-label">Product selection</span>
            </div>
          </div>
          <div class="steps-container">
            <div class="step-head-container">
              <div class="step-indicator">2</div>
              <span class="step-label">Requirements</span>
            </div>
          </div>
          <div class="steps-container">
            <div class="step-head-container">
              <div class="step-indicator">3</div>
              <span class="step-label">Contact details</span>
            </div>
          </div>
        </div>
      `;
      form.prepend(stepProgress);

      const stepButtons = document.createElement('div');
      stepButtons.className = 'step-buttons';

      const backBtn = document.createElement('button');
      backBtn.type = 'button';
      backBtn.id = 'backBtn';
      backBtn.textContent = 'Back';

      const nextBtn = document.createElement('button');
      nextBtn.type = 'button';
      nextBtn.id = 'nextBtn';
      nextBtn.textContent = 'Next';

      stepButtons.appendChild(nextBtn);

      const hsSubmit = form.querySelector('.hs_submit');
      if (hsSubmit) {
        form.insertBefore(stepButtons, hsSubmit);
      }

      const indicators = document.querySelectorAll('.step-indicator');
      const totalSteps = 3;
      let currentStep = 0;

      const updateStep = (step) => {
  allFields.forEach(field => {
    const input = field.querySelector('input, select, textarea');
    const name = input?.name;
    field.style.display = stepFields[step].includes(name) ? 'block' : 'none';
  });

  const consentText = form.querySelector('.legal-consent-container');
  if (consentText) {
    consentText.style.display = step === 2 ? 'block' : 'none';
  }

  if (hsSubmit) {
    hsSubmit.style.display = step === 2 ? 'flex' : 'none';
  }

  // Reset Back button position
  if (backBtn.parentElement) backBtn.parentElement.removeChild(backBtn);

  if (step === 2) {
    // Step 3: Move Back into submit block
    backBtn.style.display = 'inline-block';
    hsSubmit.prepend(backBtn);
  } else if (step === 1) {
    // Step 2: Show Back in step-buttons
    backBtn.style.display = 'inline-block';
    stepButtons.insertBefore(backBtn, nextBtn);
  } else {
    backBtn.style.display = 'none';
  }

  nextBtn.style.display = step === 2 ? 'none' : 'inline-block';

  indicators.forEach((el, i) => {
    el.classList.toggle('active', i === step);
    if (i < step) {
      el.classList.add('completed');
    } else {
      el.classList.remove('completed');
    }
  });
};

      const validateStep = (step) => {
        let valid = true;
        stepFields[step].forEach(name => {
          const field = form.querySelector(`[name="${name}"]`);
          if (field) {
            const wrapper = field.closest('.hs-form-field');
            const errorBox = wrapper?.querySelector('.hs-error-msgs');
            if (field.hasAttribute('required') && !field.value.trim()) {
              valid = false;
              if (errorBox) errorBox.style.display = 'block';
              field.classList.add('input-error');
            } else {
              if (errorBox) errorBox.style.display = 'none';
              field.classList.remove('input-error');
            }
          }
        });
        return valid;
      };

      updateStep(currentStep);

      nextBtn.addEventListener('click', () => {
        if (currentStep < totalSteps - 1 && validateStep(currentStep)) {
          currentStep++;
          updateStep(currentStep);
        }
      });

      backBtn.addEventListener('click', () => {
        if (currentStep > 0) {
          currentStep--;
          updateStep(currentStep);
        }
      });
    }, 100);
  }
});
</script>

we have this field that comes when we selecta one of checkbox and I want this field will show in 1st step only

Assistant
To ensure that a **conditional field** (which appears after selecting a checkbox) **always shows in Step 1** (even if it's hidden initially and revealed dynamically), you just need to include its field name in the `stepFields[0]` array.

### ✅ Step-by-step fix:

1. **Find out the name attribute** of the conditional field (the one that appears after selecting a checkbox).
– You can inspect the HTML in the browser once the checkbox is selected and the field becomes visible.
– Example: Let’s say the field that appears has this name: `hs_konversionsziel`.

2. **Update your `stepFields[0]`** definition by adding the conditional field name to it.

### ✅ Example update in your JavaScript:

Find this block:

const stepFields = {
  0: ['welche_produkte_wollen_sie_live_sehen_', 'bereits_sap_business_bydesign_kunde_'],
  1: ['message'],
  2: []
};

Update it like this (adding the conditional field):

const stepFields = {
  0: [
    'welche_produkte_wollen_sie_live_sehen_',
    'bereits_sap_business_bydesign_kunde_',
    'hs_konversionsziel' // <-- add your conditional field name here
  ],
  1: ['message'],
  2: []
};

> 🔁 Replace `'hs_konversionsziel'` with the actual `name` of your conditional field if it's different.

This ensures the field will always be **visible only in Step 1**, regardless of when it appears due to user interaction.

Let me know the exact field name if you want me to adjust this for you precisely.

User
bereits_sap_business_bydesign_kunde_ this is the conditonal field
Assistant
Perfect — since `bereits_sap_business_bydesign_kunde_` is the conditional field and you already have it listed in Step 1 (`stepFields[0]`), you're halfway there.

However, because it's conditionally **shown/hidden by HubSpot script** after the form loads (e.g., when a checkbox is clicked), we need to **force it to stay visible in Step 1** even if it's dynamically injected later.

### ✅ What You Need to Do:

After your `updateStep(currentStep)` function call inside the interval, we can add a little script to ensure this conditional field stays visible **only in Step 1** when it appears.

### ✏️ Add This Code Inside `updateStep()` (at the end of the function):

// Special case: Ensure conditional field always appears in Step 1 if visible
const conditionalField = form.querySelector('[name="bereits_sap_business_bydesign_kunde_"]')?.closest('.hs-form-field');
if (conditionalField) {
  if (currentStep === 0) {
    conditionalField.style.display = 'block';
  } else {
    conditionalField.style.display = 'none';
  }
}

### ✅ Final Look (part of `updateStep` function):

const updateStep = (step) => {
  allFields.forEach(field => {
    const input = field.querySelector('input, select, textarea');
    const name = input?.name;
    field.style.display = stepFields[step].includes(name) ? 'block' : 'none';
  });

  const consentText = form.querySelector('.legal-consent-container');
  if (consentText) {
    consentText.style.display = step === 2 ? 'block' : 'none';
  }

  if (hsSubmit) {
    hsSubmit.style.display = step === 2 ? 'flex' : 'none';
  }

  if (backBtn.parentElement) backBtn.parentElement.removeChild(backBtn);

  if (step === 2) {
    backBtn.style.display = 'inline-block';
    hsSubmit.prepend(backBtn);
  } else if (step === 1) {
    backBtn.style.display = 'inline-block';
    stepButtons.insertBefore(backBtn, nextBtn);
  } else {
    backBtn.style.display = 'none';
  }

  nextBtn.style.display = step === 2 ? 'none' : 'inline-block';

  indicators.forEach((el, i) => {
    el.classList.toggle('active', i === step);
    if (i < step) {
      el.classList.add('completed');
    } else {
      el.classList.remove('completed');
    }
  });

  // ✅ Ensure conditional field stays visible in step 1 only
  const conditionalField = form.querySelector('[name="bereits_sap_business_bydesign_kunde_"]')?.closest('.hs-form-field');
  if (conditionalField) {
    conditionalField.style.display = step === 0 ? 'block' : 'none';
  }
};

Let me know if you'd like to make it transition smoothly or control nested dependent fields too.

User
<style>
.hub-multistep-btn {
  background-color: #00b4d5;
  border-radius: 25px;
  font-weight: 600;
  min-height: 40px;
  cursor: pointer;
  width: 100%;
  font-size: 15px;
  text-align: center;
  transition: all .3s;
  fill: #fff;
}

#step-progress {
  margin: 20px 0;
  text-align: center;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.step-indicator {
  display: inline-block;
  width: 30px;
  height: 30px;
  line-height: 30px;
  border-radius: 50%;
  margin: 0 5px;
  font-size: 10px;
  font-weight: 600;
  position: relative;
  text-align: center;
  border: 1px solid #000221;
  color: #000221;
}

.step-indicator.active {
  background-color: #00b4d5 !important;
  border-color: #00b4d5 !important;
  color: #a8eeff;
}
.step-indicator.completed {
    background-color: #000221 !important;
    border: 1px solid #5fdb3a;
    color: #fafafa;
}

.step-head-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  position: relative;
}
.steps-container {
  display: flex;
  position: relative;
}
.steps-container:not(:last-child)::after {
    content: '';
    position: absolute;
    top: 15px;
    left: 80%;
    right: -270%;
    height: 1px;
    background-color: #babfc5;
    z-index: 0;
}
.step-head-container.completed .step-indicator {
  background-color: #000221 !important;
  border: 1px solid #5fdb3a;
  color: #fafafa;
}
.hs_test___letzte_konversion__asset_tag_ {
  display: none !important;
}
span.hs-form-required {
  padding-left: 5px;
  color: #9b0077;
}
.hs-form-field input:not([type=checkbox]), .hs-form-field select, .hs-input.hs-fieldtype-textarea {
  color: #000221;
  font-size: 18px;
  height: 45px;
  transition: border-bottom .2s ease-in-out, background-color .2s ease-in-out, color .2s ease-in-out;
  width: 100% !important;
  background-color: #fff ;
  border: 1px solid #ccccd3;
  border-radius: 6px !important;
  padding: 10px;
}
.hs_hs_language {
  display: none !important;
}
.hs-form-private fieldset {
  margin-bottom: 0 !important;
}
.step-buttons {
  margin-top: 30px;
  text-align: center;
  display: flex;
  gap: 12px;
}
.step-head-container.completed .step-indicator {
  background-color: #000221 !important;
  border: 1px solid #5fdb3a;
  color: #fafafa;
}
.step-buttons button {
  background-color: #00b4d5;
  border: 1px solid #00b4d5;
  border-radius: 25px;
  font-weight: 600;
  min-height: 40px;
  cursor: pointer;
  width: 100%;
  font-size: 15px;
  text-align: center;
  transition: all .3s;
  fill: #fff;
  color: #fff;
  flex: 1;
}
.step-buttons button#nextBtn:hover {
  background-color: #0092ad !important;
  color: #fff !important;
}
.step-buttons button#backBtn {
  background-color: #fff;
  color: #00b4d5;
  border: 1px solid #00b4d5;
}
.step-buttons button#backBtn:hover {
  background-color: #00b4d5;
  color: #fff;
}
.hs-form-field {
  margin-bottom: 20px;
}
.input-error {
  border-color: red !important;
}
.hs-error-msgs {
  display: block !important;
  color: red;
  font-size: 14px;
  margin-top: 4px;
}
.hs-input[type=checkbox] {
  appearance: none;
  background-color: #fff ;
  border: 1px solid #717e86;
  border-radius: 4px;
  cursor: pointer;
  height: 30px;
  width: 30px !important;
  transition: background-color .2s ease, border .5s ease;
}
.hs-input[type=checkbox]:checked {
  background-color: #00b4d5 !important;
}
.hs-input[type=checkbox]:checked:after {
  background-color: #00b4d5;
  border-radius: 50%;
  color: #fff;
  content: "✓";
  display: flex;
  border: 1px solid #fff;
  font-size: 11px;
  justify-content: center;
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 16px;
  height: 18px;
}
.hs_welche_produkte_wollen_sie_live_sehen_ label > span:first-child {
  font-size: 14px;
  font-weight: 500;
  line-height: 30px;
  text-align: left;
  color: #33354d;
}
.hs_submit.hs-submit {
  width: 100%;
  display: flex;
  gap: 12px;
  justify-content: center;
  margin-top: 30px;
}
input.hs-button.primary.large {
  width: 100%;
  padding: 0;
}
input:focus, textarea:focus, select:focus {
  background-color: #eaf8fc !important;
  border: 1px solid #00b4d5;
  box-shadow: none !important;
  color: #000221;
  outline: none !important;
}
.hs-form-private ul li {
  margin-block: 10px;
}
.hs-form-booleancheckbox label, .hs-form-checkbox label {
  align-items: center;
}
.hs-submit button#backBtn {
    background-color: #fff;
    color: #00b4d5;
    border: 1px solid #00b4d5;
    border-radius: 25px;
    font-weight: 600;
    min-height: 40px;
    width: 100%;
    font-size: 15px;
    text-align: center;
    transition: all .3s;
    fill: #fff;
}
.hs_submit .actions {
    width: 100%;
}
span.step-label {
    font-size: 12px;
    font-weight: 700;
}
</style>
<script>

</script>
<script>
hbspt.forms.create({
  portalId: "6868748",
  formId: "7e1746ed-1467-45f2-b011-d8edae5509a5",
  target: "#hubspot-form-2",
  onFormReady: function () {
    const waitForFields = setInterval(() => {
      const form = document.querySelector('#hubspot-form-2 form');
      const allFields = form?.querySelectorAll('.hs-form-field');
      if (!form || !allFields || allFields.length < 5) return;

      clearInterval(waitForFields);

      const stepFields = {
        0: ['welche_produkte_wollen_sie_live_sehen_','bereits_sap_business_bydesign_kunde_'],
        1: ['message'],
        2: []
      };

      allFields.forEach(field => {
        const input = field.querySelector('input, select, textarea');
        if (input && input.name && !Object.values(stepFields).flat().includes(input.name)) {
          stepFields[2].push(input.name);
        }
      });

      const stepProgress = document.createElement('div');
      stepProgress.innerHTML = `
        <div id="step-progress">
          <div class="steps-container">
            <div class="step-head-container">
              <div class="step-indicator active">1</div>
              <span class="step-label">Product selection</span>
            </div>
          </div>
          <div class="steps-container">
            <div class="step-head-container">
              <div class="step-indicator">2</div>
              <span class="step-label">Requirements</span>
            </div>
          </div>
          <div class="steps-container">
            <div class="step-head-container">
              <div class="step-indicator">3</div>
              <span class="step-label">Contact details</span>
            </div>
          </div>
        </div>
      `;
      form.prepend(stepProgress);

      const stepButtons = document.createElement('div');
      stepButtons.className = 'step-buttons';

      const backBtn = document.createElement('button');
      backBtn.type = 'button';
      backBtn.id = 'backBtn';
      backBtn.textContent = 'Back';

      const nextBtn = document.createElement('button');
      nextBtn.type = 'button';
      nextBtn.id = 'nextBtn';
      nextBtn.textContent = 'Specify requirements';

      stepButtons.appendChild(nextBtn);

      const hsSubmit = form.querySelector('.hs_submit');
      if (hsSubmit) {
        form.insertBefore(stepButtons, hsSubmit);
      }

      const indicators = document.querySelectorAll('.step-indicator');
      const totalSteps = 3;
      let currentStep = 0;

      const updateStep = (step) => {
  allFields.forEach(field => {
    const input = field.querySelector('input, select, textarea');
    const name = input?.name;
    field.style.display = stepFields[step].includes(name) ? 'block' : 'none';
  });

  const consentText = form.querySelector('.legal-consent-container');
  if (consentText) {
    consentText.style.display = step === 2 ? 'block' : 'none';
  }

  if (hsSubmit) {
    hsSubmit.style.display = step === 2 ? 'flex' : 'none';
  }
  nextBtn.textContent = step === totalSteps - 2 ? 'Enter contact details' : 'Specify requirements';

  // Reset Back button position
  if (backBtn.parentElement) backBtn.parentElement.removeChild(backBtn);

  if (step === 2) {
    // Step 3: Move Back into submit block
    backBtn.style.display = 'inline-block';
    hsSubmit.prepend(backBtn);
  } else if (step === 1) {
    // Step 2: Show Back in step-buttons
    backBtn.style.display = 'inline-block';
    stepButtons.insertBefore(backBtn, nextBtn);
  } else {
    backBtn.style.display = 'none';
  }

  nextBtn.style.display = step === 2 ? 'none' : 'inline-block';

  indicators.forEach((el, i) => {
    el.classList.toggle('active', i === step);
    if (i < step) {
      el.classList.add('completed');
    } else {
      el.classList.remove('completed');
    }
  });
  const conditionalField = form.querySelector('[name="bereits_sap_business_bydesign_kunde_"]')?.closest('.hs-form-field');
if (conditionalField) {
  if (currentStep === 0) {
    conditionalField.style.display = 'block';
  } else {
    conditionalField.style.display = 'none';
  }
}
};

      const validateStep = (step) => {
        let valid = true;
        stepFields[step].forEach(name => {
          const field = form.querySelector(`[name="${name}"]`);
          if (field) {
            const wrapper = field.closest('.hs-form-field');
            const errorBox = wrapper?.querySelector('.hs-error-msgs');
            if (field.hasAttribute('required') && !field.value.trim()) {
              valid = false;
              if (errorBox) errorBox.style.display = 'block';
              field.classList.add('input-error');
            } else {
              if (errorBox) errorBox.style.display = 'none';
              field.classList.remove('input-error');
            }
          }
        });
        return valid;
      };

      updateStep(currentStep);

      nextBtn.addEventListener('click', () => {
        if (currentStep < totalSteps - 1 && validateStep(currentStep)) {
          currentStep++;
          updateStep(currentStep);
        }
      });

      backBtn.addEventListener('click', () => {
        if (currentStep > 0) {
          currentStep--;
          updateStep(currentStep);
        }
      });
    }, 100);
  }
});
</script>

in above code Please complete this required field showing to times display one at a time

Assistant
To ensure the **required field error message for `bereits_sap_business_bydesign_kunde_`** (or any other) appears only once in your HubSpot multi-step form, the issue is likely due to HubSpot re-appending the error “ or your code displaying it manually alongside HubSpot’s default behavior.

Here’s how you can **fix duplicate error message display**:

### ✅ Fix in `validateStep()`:
Right now, your code manually shows the error message using:

if (errorBox) errorBox.style.display = 'block';

But **HubSpot already handles validation errors** and renders `.hs-error-msgs` by itself. You should **not force it to display manually**, only highlight the input.

### ✅ Updated `validateStep()` (Replace your existing one with this):

const validateStep = (step) => {
  let valid = true;
  stepFields[step].forEach(name => {
    const field = form.querySelector(`[name="${name}"]`);
    if (field) {
      const wrapper = field.closest('.hs-form-field');
      const errorBox = wrapper?.querySelector('.hs-error-msgs');
      if (field.hasAttribute('required') && !field.value.trim()) {
        valid = false;
        field.classList.add('input-error');
        if (errorBox) {
          // Only display one error message (remove duplicates if any)
          const existingErrors = wrapper.querySelectorAll('.hs-error-msgs');
          if (existingErrors.length > 1) {
            for (let i = 1; i < existingErrors.length; i++) {
              existingErrors[i].remove();
            }
          }
          errorBox.style.display = 'block';
        }
      } else {
        field.classList.remove('input-error');
        if (errorBox) errorBox.style.display = 'none';
      }
    }
  });
  return valid;
};

### ✅ Explanation of Changes:
– Prevents duplicate `.hs-error-msgs` blocks from stacking inside the same `.hs-form-field`.
– Keeps default HubSpot validation behavior intact.
– Ensures user sees the error just once per field.

Let me know if you'd like to scroll to the first error or highlight it with a shake/focus effect.

User
NOt working still shwojng 2 errors
Assistant
Thanks for confirming — since the error is still showing twice, that means:
1. HubSpot **automatically generates** its own error message in `.hs-error-msgs`.
2. Your code is **manually re-showing** or HubSpot is **adding a duplicate on re-validation**.

We’ll fix this cleanly by:
– **Never manually showing** the `.hs-error-msgs`.
– **Removing duplicates** before each validation cycle.

### ✅ Final Fix: Use this **cleaned and strict** version of `validateStep()`:

const validateStep = (step) => {
  let valid = true;

  // Loop through all fields for the current step
  stepFields[step].forEach(name => {
    const field = form.querySelector(`[name="${name}"]`);
    if (field) {
      const wrapper = field.closest('.hs-form-field');
      
      // Remove duplicate error messages (keep only the first)
      const allErrorMsgs = wrapper.querySelectorAll('.hs-error-msgs');
      if (allErrorMsgs.length > 1) {
        for (let i = 1; i < allErrorMsgs.length; i++) {
          allErrorMsgs[i].remove();
        }
      }

      const errorBox = wrapper.querySelector('.hs-error-msgs');

      if (field.hasAttribute('required') && !field.value.trim()) {
        valid = false;
        field.classList.add('input-error');

        // Let HubSpot show error messages naturally — do NOT force display
        if (errorBox) errorBox.style.display = '';
      } else {
        field.classList.remove('input-error');
        if (errorBox) errorBox.style.display = 'none';
      }
    }
  });

  return valid;
};

### 🔁 Why This Works:
– It removes all extra “ elements beyond the first.
– It **lets HubSpot control error display**, preventing duplication from manual `display: block`.
– It only visually highlights the field with `.input-error` class.

If it's still not behaving, I can log the exact structure of `form.querySelector('.hs-form-field')` live to track duplicates.

Would you like to **auto-scroll to the first error** too when clicking "Next"?

User
still showing 2 times
Assistant
Thanks for your patience, Neeraj. Since it's **still showing two identical error messages**, here's what's really happening:

### 🔍 Root Cause
– HubSpot sometimes **injects duplicate `.hs-error-msgs`** during dynamic validation (especially for fields that appear conditionally).
– Your manual validation + HubSpot’s own validation are **both injecting messages**.

### ✅ Bulletproof Fix Strategy

Let’s **completely clear out old error messages** **before every step validation**, and let **HubSpot auto-validate** only after form submission.

We'll take over the field validation **fully on the client side** in the step logic.

### ✅ Updated Working `validateStep()` Function

Replace your entire existing `validateStep` with this:

const validateStep = (step) => {
  let valid = true;

  stepFields[step].forEach(name => {
    const field = form.querySelector(`[name="${name}"]`);
    if (!field) return;

    const wrapper = field.closest('.hs-form-field');

    // Remove ALL existing hs-error-msgs for this field
    const errorBoxes = wrapper.querySelectorAll('.hs-error-msgs');
    errorBoxes.forEach(el => el.remove());

    // Remove custom error class
    field.classList.remove('input-error');

    // Validate manually
    if (field.hasAttribute('required') && !field.value.trim()) {
      valid = false;
      field.classList.add('input-error');

      // Append fresh single error message
      const newError = document.createElement('ul');
      newError.className = 'hs-error-msgs inputs-list';
      newError.innerHTML = `<li>This field is required.</li>`;
      wrapper.appendChild(newError);
    }
  });

  return valid;
};

### ✅ Bonus: Add This to CSS (if not already)

Just in case:

.input-error {
  border-color: red !important;
}
.hs-error-msgs {
  color: red;
  font-size: 14px;
  margin-top: 4px;
  list-style: none;
  padding-left: 0;
}

### 🧪 Optional Debug Tip
Add this temporarily in the `validateStep` loop to check error count:

console.log(`Validating ${name}:`, wrapper.querySelectorAll('.hs-error-msgs').length);

This will **force only one visible error per field**, no matter how often it's re-validated or conditionally displayed.

Let me know if you want it to **scroll to the first error** automatically too.

User
Okay not show
Please fill in all required fields. this error in step 1 and step 2 if click submit button at 3rd step
Assistant
Got it. You're now seeing HubSpot's global error —
**"Please fill in all required fields."** — even though you're using a multi-step setup and already validated fields step-by-step.

This happens because:
– HubSpot's native validation **still runs on submit**, and it tries to validate **hidden fields** from previous steps.
– Even if those fields are valid, their `display: none` makes HubSpot **think they are missing**.

### ✅ Solution: Prevent HubSpot from validating hidden fields

We’ll **disable all hidden fields before submission**, so HubSpot **skips** them.

### 🔧 Add This to Your `updateStep()` Function – Inside `if (hsSubmit)` block at step 2:

// In Step 3, disable hidden fields to prevent HubSpot validation errors
const manageFieldVisibility = () => {
  allFields.forEach(field => {
    const input = field.querySelector('input, select, textarea');
    const isVisible = stepFields[currentStep].includes(input?.name);
    if (input) {
      if (isVisible) {
        input.disabled = false;
        field.style.display = 'block';
      } else {
        input.disabled = true; // Prevent HubSpot from validating it
        field.style.display = 'none';
      }
    }
  });
};

Then call this at the **end of `updateStep(step)`**:

manageFieldVisibility(); // Add this to the very end of updateStep

### ✅ Why This Works:
– HubSpot **ignores disabled fields**, so it doesn't throw "Please fill in all required fields".
– This doesn’t interfere with your manual validation.
– Fields from previous steps remain intact and get submitted.

Let me know if you'd like to **re-enable all fields** just before submission too (e.g., if you're using server-side validation post-submit).

User
No, I just want to hide validation message on step 1 and step 2
Assistant
Got it — you want to **suppress HubSpot's global "Please fill in all required fields."** message from showing on **Step 1 and Step 2**, and only allow it on **Step 3 (the actual submit step)**.

### ✅ How to Do That

We'll **detect and hide** that global validation message **unless you're on Step 3**.

### 🔧 Add This Inside Your `updateStep(step)` Function (at the end):

// Hide global error message unless on final step
const globalError = form.querySelector('.hs-error-msg');
if (globalError) {
  globalError.style.display = step === 2 ? 'block' : 'none';
}

Place this right after:

manageFieldVisibility(); // or wherever your last line is in updateStep

### ✅ Optional: If HubSpot shows it in a different class

Sometimes it uses `.hs-error-msgs` or `.hs-error-msg.likely-error`. If the one above doesn't work, try this more flexible version:

document.querySelectorAll('.hs-error-msg').forEach(el => {
  el.style.display = currentStep === 2 ? 'block' : 'none';
});

### ✅ Final Recap
– Add that small conditional check inside `updateStep()`.
– It will **auto-hide the global error message** during Step 1 and Step 2.
– On Step 3, HubSpot shows it normally if fields are still incomplete.

Let me know if you’d like to style or animate that error message on Step 3 only.

Leave a Comment

Your email address will not be published. Required fields are marked *