Client-side validation fails for bundle selection in quote configuration, allowing incomplete quotes

We’re running into a frustrating issue with quote configuration in HubSpot 2023. When sales reps try to configure quotes with bundled products, the client-side validation is failing inconsistently. The validation should check if all required bundle items are selected before allowing quote creation, but it’s letting incomplete bundles through.

The JavaScript validation fires on form submission, but when certain bundle combinations are selected, it throws errors in the console and the UI doesn’t show any feedback to the user. They think the quote is valid and submit it, only to find out later that critical bundle components are missing.

Has anyone dealt with similar bundle selection validation issues? I’m particularly concerned about the error handling and how to provide proper UI feedback when validation fails.

One thing to watch out for - if you’re using HubSpot’s native quote templates, they have their own validation layer that might conflict with your custom JavaScript. I’ve seen cases where both validations run simultaneously and cause race conditions. You might need to disable the default validation for bundle fields and handle everything in your custom code, or find a way to hook into their validation chain properly.

Thanks for the suggestions. I looked at the console errors more carefully and you’re right - the validation is firing before the bundle DOM elements are ready. Here’s what I’m seeing:

TypeError: Cannot read property 'selectedOptions' of null
at validateBundle (quote-validation.js:47)
at HTMLFormElement.handleSubmit (quote-validation.js:12)

So the bundleSelect element doesn’t exist when the validation runs. How do I properly wait for all bundle components to be loaded?

Here’s a comprehensive solution that addresses all three aspects - bundle selection validation, error handling, and UI feedback.

First, use MutationObserver to detect when bundle options are dynamically loaded:

const observer = new MutationObserver(() => {
  const bundleContainer = document.querySelector('.bundle-options');
  if (bundleContainer) validateBundleReady();
});
observer.observe(document.body, {childList: true, subtree: true});

For the validation itself, implement a comprehensive check that waits for all bundle components:

function validateBundle() {
  const required = document.querySelectorAll('[data-bundle-required="true"]');
  const missing = Array.from(required).filter(item => !item.checked);
  return {valid: missing.length === 0, missing};
}

For UI feedback, create an error display system that shows specific missing items:

function showValidationError(missingItems) {

  const errorDiv = document.getElementById('bundle-validation-error');

  errorDiv.innerHTML = `<strong>Missing required bundle items:</strong><ul>${missingItems.map(item => `<li>${item.dataset.itemName}</li>`).join('')}</ul>`;

  errorDiv.setAttribute('role', 'alert');

}

The key is handling the timing issue with MutationObserver instead of relying on fixed delays or load events. This ensures your validation always runs after HubSpot has finished rendering the bundle options. Wrap your form submission handler to prevent invalid quotes from being created:

form.addEventListener('submit', (e) => {

  const validation = validateBundle();

  if (!validation.valid) {

    e.preventDefault();

    showValidationError(validation.missing);

  }

});

This approach solves the null reference errors by waiting for actual DOM presence, provides clear error messaging to users, and prevents incomplete bundles from being submitted. Make sure to test with different bundle configurations, especially when products are added or removed dynamically during quote creation.

I’ve seen this before. Usually it’s because the validation event listener isn’t properly bound to dynamically loaded bundle options. When you add products to a bundle, HubSpot loads those options via AJAX, and your validation code might be checking the DOM before those elements exist. Try using event delegation on a parent container instead of direct binding.

For the UI feedback issue, you need to implement proper error state management. Even if you fix the timing, users won’t know what’s wrong without visual indicators. I recommend adding a validation message container near your bundle selector and updating it with specific error messages. Something like “Please select all required items in the bundle” with a list of missing components. Use aria-live regions for accessibility too.