Debut "bug" with current_variant.available

I’d really like a solution, if one exists, for the following behavour. I suspect it’s a bug or limitation of the theme/Shopify, but surely there is a workaround of some description?

My store/product is here (password “omicron” without quotes)

If I put the following in product-template.liquid (doesn’t really matter where, but let’s say just below the product description)

{% assign current_variant = product.selected_or_first_available_variant %}

 {{current_variant.available }} 

Then it is only correct on the first load of a product - i.e. it only applies to the default variant. If that is in stock, then “true” is printed, and if not “false” is printed.

If I choose another variant then it will remain in the previous state. If I load a page with the default (or deeplinked) variant is in stock (“true” is shown) and change to a variant that is not available then it remains “true”.

Is it possible to change it so that current_variant updates?

If I put the following, the sku updates with variant selection without any problems. It’s correct every time, but availability doesn’t update correctly.


{{ current_variant.sku }}

I have also found that bypassing “assign” and using the following does not update like I think it should.


 {{ product.selected_or_first_available_variant.available }} 

The following code produced the following results with no F5 of the page, just choosing from the stadard Debut product variant selector.

{% assign current_variant = product.selected_or_first_available_variant %}
            {% assign in_stock = current_variant.available %}
			{{ current_variant.sku }}
            

 {{ current_variant.available }} 

            

 {{ product.selected_or_first_available_variant.available }} 

            

 {{ in_stock }} 

            {% unless in_stock %}
            

 false 

            {% endunless %}

Liquid is pre-processed, it has no concept of what happens after the code it generates is sent to the browser. Once in the browser you need to use JS get this information and provide interactivity.

So how come price, sku, pictures are updated, but availability isn’t? Is it ultimately an omission from theme.js?

It is available in the product JSON generated in the product template:

theme.js reads this json data to get product data. Starting at line 7983 of your theme.js file.

@tristancliffe

This is not a bug nor a limitation per se. Liquid is unable to watch or perform real time changes; it processes one single value.
What’s responsible for updating and watching changes is Javascript.

Therefore, as aforementioned, the JSON is available to allow you to update the UI upon changes. Developers can then wire it all up with JS and code whichever functionalities they wish.

You can fetch the current product’s data in JSON format via the current product’s URL plus “.json” at the end. Like this:

website.com/products/product-name.json

( https://shop.omicron.uk.com/products/brake-pads.json in your case).

Kind regards,
Diego

@iDoThemes @diego_ezfy

Thank you.

I’m have zero experience with JS, but it strikes me that the following code SHOULD update the visible page, and works for changing the price, showing “sold out” next to the price, changing the add to cart button etc when changing variants. So I don’t really understand why the existing (working) JS doesn’t kick in for other elements when changing the selected variant.

_initVariants: function() {
      var options = {
        container: this.container,
        enableHistoryState:
          this.container.getAttribute('data-enable-history-state') === 'true',
        singleOptionSelector: this.selectors.singleOptionSelector,
        originalSelectorId: this.selectors.originalSelectorId,
        product: this.productSingleObject
      };

      this.variants = new slate.Variants(options);
      if (this.storeAvailability && this.variants.currentVariant.available) {
        this.storeAvailability.updateContent(this.variants.currentVariant.id);
      }

      this.eventHandlers.updateAvailability = this._updateAvailability.bind(
        this
      );
      this.eventHandlers.updateMedia = this._updateMedia.bind(this);
      this.eventHandlers.updatePrice = this._updatePrice.bind(this);
      this.eventHandlers.updateSKU = this._updateSKU.bind(this);

      this.container.addEventListener(
        'variantChange',
        this.eventHandlers.updateAvailability
      );
      this.container.addEventListener(
        'variantImageChange',
        this.eventHandlers.updateMedia
      );
      this.container.addEventListener(
        'variantPriceChange',
        this.eventHandlers.updatePrice
      );
      this.container.addEventListener(
        'variantSKUChange',
        this.eventHandlers.updateSKU
      );
    },

So I tried duplicating a line in product-template that works, to come up with the following code, and the original line is fine, the second line loads properly but is static. I’m so confused!


    {% include 'product-price', variant: current_variant, show_vendor: section.settings.show_vendor %}
    {% include 'product-price', variant: current_variant, show_vendor: section.settings.show_vendor %}

Edit: If I examine the page source and find the json result in the html it includes the available key, but url.json is missing the available key. Strange.

I gave up. Asking too much of my limited skills, other people’s help, and certain limitations of the Debut theme at least (or perhaps Shopify’s system).

I have added an enquiry button to all product pages that works as a mailto hyperlink at all times, regardless of stock of variant, and done a little bit of CSS to make it look part of the theme.

I also solved another problem on a product-notforsale template (where I didn’t want prices, add to cart etc to show) by using the class “visually-hidden” to hide elements I didn’t want without it breaking the javascript and stopping the menu from working.

Thanks for all the assistance and tips and for being patient with me (and people like me).