React to variant change to display/hide text depending on availability

Topic summary

Goal: Show/hide availability text in Dawn based on the currently selected product variant, not just the initially rendered one.

Issue: Liquid condition product.selected_or_first_available_variant.available only evaluates on initial render and doesn’t update when variants change.

Suggestions:

  • React with JavaScript based on the variant change reflected in the URL (?variant=ID).
  • Optionally expose product config on window and/or add data attributes to variant options to map selection to availability.

Current implementation:

  • Pre-render per-variant HTML blocks (with data-variant-id) for “available” vs “not available,” all hidden by default.
  • On load and on URL changes, show the block matching the current variant ID; if none, show the first.
  • Detect URL changes via MutationObserver; parse window.location.search to get the variant ID.

Caveat/Recent update:

  • Depending on the theme, the URL may be updated after the MutationObserver callback runs, so the url !== lastUrl check can miss changes. A more reliable hook into the theme’s variant change lifecycle may be needed.

Status: Working prototype using URL-driven updates, but reliability depends on theme behavior; no final resolution.

Summarized with AI on December 11. AI used: gpt-5.

Thanks for the hint. This is my current solution:

  1. Loop over all variants and create the correct HTML with data-variant-id, hide it with display: none
{% for variant in product.variants %}

   {%- if variant.available -%}
      
Content Available

   {%- else -%}
      Content Not Available

   {%- endif -%}

{% endfor %}
  1. Detect current variant and show the right content
// Add observer to detect url change. This will call "onUrlChange()"
let lastUrl = location.href;
new MutationObserver(() => {
    const url = location.href;
    if (url !== lastUrl) {
        lastUrl = url;
        onUrlChange();
    }
}).observe(document, {subtree: true, childList: true});

// Initialise the correct variant on page load
updateVariants();

// Update variant on url change
function onUrlChange() {
    updateVariants();
}

function updateVariants()
{
    // get the current variantId (or null if initial page load)
    const variantId = getCurrentVariantId();
    // get all created variant contents
    const elements = document.querySelectorAll("[data-variant-id]");
    let first = true;
    elements.forEach(el => {
        let display = 'none'
        // either show the one for the current variantId OR the first one, if no variantId is given (first page load)
        if ((variantId && el.getAttribute('data-variant-id') === variantId) || (!variantId && first)) {
            display = 'block';
        }
        first = false;
        el.style.display = display
    })
}

// get the variantId from the URL (or null if initial page load)
function getCurrentVariantId() {
    const params = new URLSearchParams(window.location.search)
    let variantId = null;
    if (params.has("variant")) {
        variantId = params.get("variant");
    }
    return variantId;
}