Looking for app that allows conditional variants with inventory tracking for all options

ChrisCost
Visitor
2 0 0

Hi, I was looking for an app that would allow us to have a conditional option for specific variants of two different size shirts, that would also allow us to input and track inventory of those specific variants.


For example, we have a product: Sports Jersey (Blue). This  jersey comes in Medium and XL, with the numbers on the jersey 1-20 being Medium and 21-45 being XL. So I need to be able to allow a customer to choose a size, and then have a menu appear to have them choose which number they want (so they can choose Medium, and then check which numbers from 1-20 they need, or choose XL and choose from 21-45).
 
I've found a few apps that, from my short testing, seem to almost have what we need, but either don't allow the limitation of specific numbers to their respective size (so all 45 numbers would be available to both sizes, which won't work), or, in the case of all apps I've tried, maybe 6 by now, don't have an option to input inventory quantities for every number. We may only have a few of Medium #16 in stock, but I haven't found an option on any app yet to be able to input this info. 
Reply 1 (1)

EasifyApps-Zoe
Shopify Partner
582 14 44

Hi @ChrisCost,

You may not require a third-party app to achieve this. Instead, you can implement custom code in your theme to hide unavailable combinations of variants. Follow the steps below to accomplish this 😊:

  1. Start by creating your Sports Jersey (Blue) product. Add 2 options - "Size" and "Number", and define your variants accordingly (e.g., size M, XL, and numbers 1-45). Remove any unavailable variants, such as M 21-45 and XL 1-20, and specify the inventory for the available variants.

  2. Access your theme editor and navigate to the Products template. In the "Product Information" section, click on "Add block," and select the "Custom liquid" block.

  3. Now, insert the following code into the Custom liquid field. This code will automatically hide any unavailable variant combinations. As a result, when customers select size M, they will only see numbers 1-20 as their choices. If they choose XL, they will see numbers 21-45.

 

<script language="javascript" type="text/javascript">
const pickerType = (document.querySelector('variant-radios')) ? 'radios' : 'selects';
const variantSelects = (pickerType == 'radios') ? document.querySelector('variant-radios') : document.querySelector('variant-selects');
const fieldsets = (pickerType == 'radios') ? Array.from(variantSelects.querySelectorAll('fieldset')) : Array.from(variantSelects.querySelectorAll('.product-form__input--dropdown'));
const productJson = JSON.parse(variantSelects.querySelector('[type="application/json"]').textContent);
let selectedOptions = [];

variantSelects.addEventListener('change', rebuildOptions);
this.rebuildOptions();

// gather a list of valid combinations of options, check to see if the input passed to it matches in a chain of valid options.
function validCombo(inputValue, optionLevel) {
  for(let i = 0; i < productJson.length; i++) {
    if(optionLevel == 1){
      if (productJson[i].option1 == selectedOptions[0] && productJson[i].option2 == inputValue) { return true; }
    } else {
      if (productJson[i].option1 == selectedOptions[0] && productJson[i].option2 == selectedOptions[1] && productJson[i].option3 == inputValue) { return true; }
    }
  }
  return false;
}

function rebuildOptions() {
  selectedOptions = fieldsets.map((fieldset) => {
    return (pickerType == 'radios') ? Array.from(fieldset.querySelectorAll('input')).find((radio) => radio.checked).value : Array.from(fieldset.querySelectorAll('select'), (select) => select.value);
  });
  //loop through the option sets starting from the 2nd set and disable any invalid options
  for(let optionLevel = 1, n = fieldsets.length; optionLevel < n; optionLevel++) {
    const inputs = (pickerType == 'radios') ? fieldsets[optionLevel].querySelectorAll('input') : fieldsets[optionLevel].querySelectorAll('option');

    inputs.forEach(input => {
      input.disabled = (validCombo(input.value,optionLevel)) ? false : true;
      if(pickerType == 'radios'){
        //get the label for the current input (this is what the user clicks, the "pill")
        const label = fieldsets[optionLevel].querySelector(`label[for="${input.id}"]`);

        label.style.display = (input.disabled) ? "none" : ""; //Hide the option, or comment this line out and use the following lines to style it..
        //label.style.opacity = (input.disabled) ? 0.5 : 1;
        //label.style.borderStyle = (input.disabled) ? "dashed" : "solid";
        //label.style.textDecoration = (input.disabled) ? "none" : "";
      } else {
        input.hidden = (validCombo(input.value,optionLevel)) ? false : true;
      }
    });
  }

  //if the default selected option is disabled with the function above, select the first available option instead
  for (let optionLevel = 1, fieldsetsLength = fieldsets.length, change = false; optionLevel < fieldsetsLength && !change; optionLevel++) {
    if(pickerType == 'radios'){
      if(fieldsets[optionLevel].querySelector('input:checked').disabled === true) {
        change = (fieldsets[optionLevel].querySelector('input:not(:disabled)').checked = true);
      }
    } else {
      if(fieldsets[optionLevel].querySelector('option:checked').disabled === true) {
        change = (fieldsets[optionLevel].querySelector('option:not(:disabled)').selected = "selected");
      }
    }
    //if a new option has been selected, restart the whole process
    if(change) variantSelects.dispatchEvent(new Event('change', { bubbles: true }));
  }
}
</script>

 

 

 

EasifyAppsZoe_0-1698635468706.pngEasifyAppsZoe_1-1698635479497.png

EasifyAppsZoe_2-1698635490622.png

EASIFY - MAKING SHOPIFY SIMPLE & SWEET!
Easify Product Options: Create custom product options 10X faster & easier!
Easify Product Attachments: Effortlessly add downloadable PDF files (or any other format) to Shopify pages!
Try for Free | 24/7 Live Chat Support