ISBN not changing with variant change from dropdown

Hi Community, We were unable to dynamically change the ISBN of a product variant when a different variant is chosen from the dropdown. When changed, the first variant’s ISBN is shown and does not update until the page is refreshed. I have also attached the code. We really need to sort this out as quickly as possible. Please help on this.

{% assign default_variant = product.variants.first %}

<!-- Display the barcode/ISBN -->
{% if default_variant.barcode != blank %}
  <div id="product-barcode">
    ISBN: {{ default_variant.barcode }}
  </div>
{% endif %}

<script>
  document.addEventListener("DOMContentLoaded", function() {
    var selectElement = document.querySelector("[name='id']");
    var barcodeElement = document.getElementById("product-barcode");

    if (selectElement && barcodeElement) {
      var variants = {{ product.variants | json }};

      selectElement.addEventListener("change", function(event) {
        var selectedVariantId = event.target.value;
        var selectedVariant = variants.find(function(variant) {
          return variant.id == selectedVariantId;
        });

        if (selectedVariant) {
          if (selectedVariant.barcode) {
            barcodeElement.innerHTML = "ISBN: " + selectedVariant.barcode;
            barcodeElement.style.display = "block";
          } else {
            barcodeElement.style.display = "none";
          }
        }
      });
    }
  });
</script>

Hi @biblionepal

To me, that selectElement looks strange, try with the following selector instead

var selectElement = document.querySelector('.variant-picker__form select');

if all your variants are in a select element.

In general, for debugging, you can use console.log to confirm that variables are ok and continue, or see if they return an unexpected value. Same for events, if they fire or not.

Nothing is wrong with the selector, however, the “change” event is not fired on this element, because this element is not changed by the visitor, only by Javascript code.

Check the answer here, for example: javascript - Why does the 'input' event not get fired when changing the value of an input field? - Stack Overflow (it’s about input, but change is the same)

The input event is an UI-Event, it’s meant to fire when the user does action the page, not when scripts do.

What you can do?

  1. use a MutationObserver to monitor this element, or
  2. listen for event fired by theme code, like these:

This event passes a combination of selected options, not a variant id, so you can either fetch the value of selectElement (easier), or check the option values against your array.

Code should be like:

    ...
  document.documentElement.addEventListener( "variant:selected", (e)=> { 
   let selectedVariantId = selectElement.value;
   let selectedVariant = variants.find...
  })

Should work ok on product page. If you have quick add modals, then the code would be more complex as you’d need to see what product generated the event.


if my post is helpful, please like it ♡ and mark as a solution -- this will help others find it

Hi, It’s not working : {% assign default_variant = product.variants.first %}

{% if default_variant.barcode %}{{ default_variant.barcode }}{% endif %}

Hey @biblionepal,

I found that in your current code you are using the Java script. It’s a client side language and it’s update the data on Page Reload. If you want that ISBN update realtime then you need to use ajax.

AJAX works realtime and without Page Refresh.

Here is the solution on ajax based.

{% comment %}
  Dynamic ISBN/Barcode Display for Product Variants
  This code handles real-time ISBN updates when variants are selected
{% endcomment %}

{% assign current_variant = product.selected_or_first_available_variant %}

<!-- Display the barcode/ISBN -->
<div id="product-barcode" {% unless current_variant.barcode != blank %}style="display: none;"{% endunless %}>
  <span class="barcode-label">ISBN: </span>
  <span id="barcode-value">{{ current_variant.barcode }}</span>
</div>

<script>
(function() {
  'use strict';
  
  // Store all variants data
  const variants = {{ product.variants | json }};
  const barcodeContainer = document.getElementById('product-barcode');
  const barcodeValue = document.getElementById('barcode-value');
  
  if (!barcodeContainer || !barcodeValue) {
    console.warn('Barcode elements not found');
    return;
  }
  
  // Function to update ISBN display
  function updateISBN(variantId) {
    const selectedVariant = variants.find(variant => variant.id == variantId);
    
    if (selectedVariant) {
      if (selectedVariant.barcode && selectedVariant.barcode.trim() !== '') {
        barcodeValue.textContent = selectedVariant.barcode;
        barcodeContainer.style.display = 'block';
        
        // Add loading state for better UX
        barcodeContainer.classList.remove('loading');
      } else {
        barcodeContainer.style.display = 'none';
      }
    }
  }
  
  // Function to get current selected variant ID
  function getCurrentVariantId() {
    // Try multiple common selectors for variant selection
    const selectors = [
      'select[name="id"]',
      'input[name="id"]:checked',
      '[data-variant-id]',
      '.product-form select',
      '.variant-selector select'
    ];
    
    for (const selector of selectors) {
      const element = document.querySelector(selector);
      if (element) {
        if (element.type === 'radio' && element.checked) {
          return element.value;
        } else if (element.tagName === 'SELECT') {
          return element.value;
        } else if (element.dataset.variantId) {
          return element.dataset.variantId;
        }
      }
    }
    
    // Fallback to URL params
    const urlParams = new URLSearchParams(window.location.search);
    return urlParams.get('variant') || {{ current_variant.id }};
  }
  
  // AJAX-based variant change handler
  function handleVariantChange(variantId) {
    if (!variantId) return;
    
    // Add loading state
    barcodeContainer.classList.add('loading');
    
    // Fetch variant data via AJAX
    fetch(`${window.location.pathname}?variant=${variantId}&view=json`, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
        'X-Requested-With': 'XMLHttpRequest'
      }
    })
    .then(response => response.json())
    .then(data => {
      // Update from AJAX response if available
      if (data && data.variant && data.variant.barcode !== undefined) {
        if (data.variant.barcode && data.variant.barcode.trim() !== '') {
          barcodeValue.textContent = data.variant.barcode;
          barcodeContainer.style.display = 'block';
        } else {
          barcodeContainer.style.display = 'none';
        }
      } else {
        // Fallback to local variant data
        updateISBN(variantId);
      }
    })
    .catch(error => {
      console.warn('AJAX request failed, using local data:', error);
      // Fallback to local variant data
      updateISBN(variantId);
    })
    .finally(() => {
      barcodeContainer.classList.remove('loading');
    });
  }
  
  // Event delegation for dynamic elements
  function setupEventListeners() {
    // Listen for changes on the document to catch dynamically added elements
    document.addEventListener('change', function(event) {
      const target = event.target;
      
      // Check if the changed element is a variant selector
      if (
        (target.name === 'id' || target.classList.contains('variant-selector') || 
         target.closest('.product-form') || target.dataset.variantSelector) &&
        target.value
      ) {
        handleVariantChange(target.value);
      }
    });
    
    // Listen for radio button clicks
    document.addEventListener('click', function(event) {
      const target = event.target;
      
      if (target.type === 'radio' && target.name === 'id') {
        handleVariantChange(target.value);
      }
    });
    
    // Listen for custom variant change events (common in themes)
    document.addEventListener('variant:change', function(event) {
      const variantId = event.detail?.variant?.id || event.detail?.id;
      if (variantId) {
        handleVariantChange(variantId);
      }
    });
    
    // Listen for Shopify's built-in variant events
    document.addEventListener('variantChange', function(event) {
      const variantId = event.detail?.variant?.id;
      if (variantId) {
        handleVariantChange(variantId);
      }
    });
  }
  
  // Initialize when DOM is ready
  function init() {
    setupEventListeners();
    
    // Set initial state
    const currentVariantId = getCurrentVariantId();
    if (currentVariantId) {
      updateISBN(currentVariantId);
    }
    
    // Watch for URL changes (for themes that update URL on variant change)
    let currentUrl = window.location.href;
    setInterval(() => {
      if (window.location.href !== currentUrl) {
        currentUrl = window.location.href;
        const newVariantId = getCurrentVariantId();
        if (newVariantId) {
          handleVariantChange(newVariantId);
        }
      }
    }, 500);
  }
  
  // Initialize immediately if DOM is ready, otherwise wait
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }
  
})();
</script>

<style>
  #product-barcode {
    margin: 10px 0;
    font-weight: 500;
  }
  
  #product-barcode.loading {
    opacity: 0.6;
  }
  
  #product-barcode.loading::after {
    content: " (updating...)";
    font-size: 0.8em;
    color: #666;
  }
  
  .barcode-label {
    font-weight: 600;
  }
</style>

If this was helpful Mark as Solution and Like it.
Best,
Daniel.

Hi, it’s not working . I have implemented it, here is the link :Buy 1984 in Nepal | BIBLIONEPAL: Bookstore in Kathmandu

If it’s still not working then there is issue with the ISBN picker rule.

By any chance can you share your Store collab code in the p/m so that I can take a look.
Thanks

Technically, all you need is this:

{% assign current_variant = product.selected_or_first_available_variant %}

<!-- Display the barcode/ISBN -->
<div id="product-barcode">
  <span class="barcode-label">ISBN: </span>
  <span id="barcode-value">{{ current_variant.barcode }}</span>
</div>

<script>
  document.addEventListener("variant:update", e => {
    const { barcode } = e?.detail?.resource;
    const barcodeElement = document.querySelector('#barcode-value');
    if (barcodeElement) barcodeElement.innerText = barcode;
  });
</script>

You’d need a bit of extra code if you want to hide ISBN line if barcode is empty.