Linked Options On Product Page

Linked Options On Product Page

Nowadays, a common feature you will see on the sites is the Linked Options on the product page. Basically, the Linked Options helps the customers to see only available variants on the site.

For eg: If on your site there are two options such as Color and size and you want that only available variants will show on your site rest all will be hide in that case we need to implement the Linked options. We need to make linking between Color and Size such as Red/XS, Blue/S is not available so for that we need to implement linked options. 

What is a Linked Options?
In Linked option we can hide your unavailable or sold-out variants by making combos and links. 

Purpose and use of Linked Options?
Basically, if we have two Options Size and colors and any of variant is sold out or not available we can hide that variant with linked options. For eg in color we have 3 options Red, blue, orange and in size we have S,X,XS and the variants Red/X is not available so to hide that variant we implement Linked option. 

 
How to achieve the Linked Options functionality:

NOTE: Firstly, All products that require reference to the Linked options must have a Size and Color option whether using app or custom code.



Basically there are two methods to achieve the functionality of a Linked Options

1. App
2. Custom code

1. By App:
We can have a Linked Options through the app and it will work absolutely fine with the app too. There are various apps which can help you to have a Linked Options on the product page. For integration of any app you can hire an experienced Shopify developer. The main drawback for using the app is that it will affect the speed as compared to custom code as custom code didn’t affect your speed of the site much but the app code can affect. Here is one of the app which can be used for this: https://apps.shopify.com/advanced-product-options 

2. By Custom code:

We can have the Linked Options functionality through custom code as well. A Professional developer can easily make the Linked Options on the product page.

The steps to achieve this functionality through custom code:

1. Basically we have to work only on the Four code files.

A) linked-options.liquid

B) theme.liquid

C) product-form.liquid



A) In the linked-options.liquid

Here is the Code:

<script>
// (c) Copyright 2016 Caroline Schnapp. All Rights Reserved. Contact: mllegeorgesand@gmail.com
// See https://docs.shopify.com/themes/customization/navigation/link-product-options-in-menus
// Modified by Jonathan Moore (Style Hatch) https://github.com/jonathanmoore
/*
Updated to work with sectioned themes
- Added required methods from the deprecated options_selection.js
- Triggers an initial variant change
- Hides sold out variants with only one option
*/
window.addEventListener('DOMContentLoaded', function() {
var Shopify = Shopify || {};
// Required functionality from depricated options_selection.js
Shopify.arrayIncludes = function(e, t) {
for (var n = 0; n < e.length; n++)
if (e[n] == t) return !0;
return !1
}, Shopify.uniq = function(e) {
for (var t = [], n = 0; n < e.length; n++) Shopify.arrayIncludes(t, e[n]) || t.push(e[n]);
return t
}
Shopify.optionsMap = {};
Shopify.updateOptionsInSelector = function(selectorIndex) {
switch (selectorIndex) {
case 0:
var key = 'root';
var selector = jQuery('.single-option-selector:eq(0)');
break;
case 1:
var key = jQuery('.single-option-selector:eq(0)').val();
var selector = jQuery('.single-option-selector:eq(1)');
break;
case 2:
var key = jQuery('.single-option-selector:eq(0)').val();
key += ' / ' + jQuery('.single-option-selector:eq(1)').val();
var selector = jQuery('.single-option-selector:eq(2)');
}
var initialValue = selector.val();
// console.log(initialValue)
selector.empty();
var availableOptions = Shopify.optionsMap[key];
for (var i=0; i<availableOptions.length; i++) {
var option = availableOptions[i];
var newOption = jQuery('<option></option>').val(option).html(option);
selector.append(newOption);
}
//console.log(selectorIndex)
jQuery('.SizeSwatchList[data-option-index="' + selectorIndex + '"] .HorizontalList__Item').each(function() {
if (jQuery.inArray($(this).attr('data-value'), availableOptions) !== -1) {
$(this).removeClass('soldout').show().find(':radio').removeAttr('disabled','disabled').removeAttr('checked');
}
else {
$(this).addClass('soldout').hide().find(':radio').removeAttr('checked').attr('disabled','disabled');
}
});
if (jQuery.inArray(initialValue, availableOptions) !== -1) {
selector.val(initialValue);
}else{
$(document).find('li[data-value="'+availableOptions[0]+'"] label').trigger('click')
}
selector.trigger('change');
};
Shopify.linkOptionSelectors = function(product) {
// Building our mapping object.
for (var i=0; i<product.variants.length; i++) {
var variant = product.variants[i];
if (variant.available) {
// Gathering values for the 1st drop-down.
Shopify.optionsMap['root'] = Shopify.optionsMap['root'] || [];
Shopify.optionsMap['root'].push(variant.option1);
Shopify.optionsMap['root'] = Shopify.uniq(Shopify.optionsMap['root']);
// Gathering values for the 2nd drop-down.
if (product.options.length > 1) {
var key = variant.option1;
Shopify.optionsMap[key] = Shopify.optionsMap[key] || [];
Shopify.optionsMap[key].push(variant.option2);
Shopify.optionsMap[key] = Shopify.uniq(Shopify.optionsMap[key]);
}
// Gathering values for the 3rd drop-down.
if (product.options.length === 3) {
var key = variant.option1 + ' / ' + variant.option2;
Shopify.optionsMap[key] = Shopify.optionsMap[key] || [];
Shopify.optionsMap[key].push(variant.option3);
Shopify.optionsMap[key] = Shopify.uniq(Shopify.optionsMap[key]);
}
}
}
// Update options right away.
Shopify.updateOptionsInSelector(0);
if (product.options.length > 1) Shopify.updateOptionsInSelector(1);
if (product.options.length === 3) Shopify.updateOptionsInSelector(2);
// When there is an update in the first dropdown.
jQuery(".single-option-selector:eq(0)").change(function() {
//console.log('here')
Shopify.updateOptionsInSelector(1);
if (product.options.length === 3) Shopify.updateOptionsInSelector(2);
return true;
});
// When there is an update in the second dropdown.
jQuery(".single-option-selector:eq(1)").change(function() {
if (product.options.length === 3) Shopify.updateOptionsInSelector(2);
return true;
});
};
{% if product.available and product.options.size > 1 %}
var $addToCartForm = $('form[action="/cart/add"]');
if (window.MutationObserver && $addToCartForm.length) {
if (typeof observer === 'object' && typeof observer.disconnect === 'function') {
observer.disconnect();
}
var config = { childList: true, subtree: true };
var observer = new MutationObserver(function() {
Shopify.linkOptionSelectors({{ product | json }});
observer.disconnect();
});
observer.observe($addToCartForm[0], config);
}
$(document).on('click','.HorizontalList li label',function(){
var par = $(this).closest('li'),
opt = $(par).attr('data-value'),
optind = $(this).closest('.HorizontalList').attr('data-option-index');
$(document).find('.single-option-selector[data-opt="'+optind+'"]').val(opt).trigger('change')
});
{% endif %}
var selector = jQuery('.single-option-selector:eq(0)');
selector.trigger('change');
{% if product.options.size == 1 %}
{% for variant in product.variants %}
{% unless variant.available %}
jQuery('.single-option-selector option').filter(function() { return jQuery(this).text().trim() === {{ variant.title | json }}; }).remove();
{% endunless %}
{% endfor %}
jQuery('.single-option-selector').trigger('change');
{% endif %}
});
</script>

B) In the theme.liquid Add the linked options snippet into your theme.liquid 1) In the Layout directory, click to open your theme.liquid file

Find the closing </body> tag. Right above the closing </body>  tag, paste the following code:
Here is the code:

{% render 'linked-options' %}

C) In the product-form.liquid

1. In the Sections directory, click to open your product-template.liquid file

2.  Paste the following code in the beginning of the product form:


{% for option in product.options_with_values %}
<select style="display:none;" class="single-option-selector" data-opt="{{ forloop.index0 }}">
{% for value in option.values %}
<option value="{{ value }}">{{ value }}</option>
{% endfor %}
</select>
{% endfor %}

D) Now in color swatch add this data parameters


{%- if color_label contains downcase_option and section.settings.show_color_swatch -%}
<ul data-option-index="{{forloop.index0}}" class="ColorSwatchList HorizontalList HorizontalList--spacingTight">
{%- for value in option.values -%}
{%- assign downcase_value = value | downcase -%}
<li data-value="{{ value }}" class="HorizontalList__Item">
{%- assign color_swatch_name = value | handle | append: '.png' -%}
{%- assign color_swatch_image = images[color_swatch_name] -%}

>> Similarly for block mode

{%- elsif section.settings.selector_mode == 'block' -%}
<ul data-option-index="{{forloop.index0}}" class="SizeSwatchList HorizontalList HorizontalList--spacingTight">
{%- for value in option.values -%}
<li data-value="{{ value }}" class="HorizontalList__Item">

Final Output :