Skip to content

Commerce Foundations is our pre-built Craft Commerce store. See what it includes

Craft CMS plugins

Variant Manager

A Craft CMS plugin that imports and exports Craft Commerce product variants from CSV files.

Variant switcher

Select a variant based on variant attribute values.

Sprig#

{% set product = craft.products.id(productId).one() %}
{% set attributeOptions = craft.variantManager.getAttributeOptions(productId) %}

{% set selection={} %}
{% for attribute in attributeOptions %}
  {# Use _context to get a variable from a string #}
  {% set selected = _context['attributeValue_' ~ loop.index] ?? attribute.values|first %}
  {% set selection = selection|merge({(attribute.name): selected}) %}
{% endfor %}

{# 
  NOTE: The "variantAttributes" below in this example should be the handle of the
  Variant Attributes field you created and have added to your variant fields layout
#}
{% set variant = craft.variants().productId(productId).variantAttributes(selection).one() %}

<h1>{{ product.title }}</h1>
{% if variant is not null %}
  <h2>{{ variant.sku }} - {{ variant.price|commerceCurrency }}</h2>
{% endif %}

<div>
  {% for attribute in attributeOptions %}
    <div>
      <label>
        {{ attribute.name }}
        <select sprig name="attributeValue_{{ loop.index }}">
          {% for value in attribute.values %}
            <option value="{{ value }}" {{ selection[attribute.name] == value ? 'selected' }}>{{ value }}</option>
          {% endfor %}
        </select>
      </label>
    </div>
  {% endfor %}
</div>

{% if variant is not null %}
  <form sprig s-method="post" s-action="commerce/cart/update-cart">
    <input type="hidden" name="purchasableId" value="{{ variant.id }}">
    <input type="submit" value="Add to cart">
  </form>
{% else %}
  <p>No matching variant found</p>
{% endif %}

{% if success is defined %}
  {{ success ? flashes.notice : flashes.error }}
{% endif %}

Alpine.js#

{% set product = craft.products.id(productId).one() %}
{% set attributeOptions = craft.variantManager.getAttributeOptions(productId) %}

{% set selection={} %}
{% for attribute in attributeOptions %}
  {# Use _context to get a variable from a string #}
  {% set selected = craft.app.request.getParam('attributeValue_' ~ loop.index) ?? attribute.values|first %}
  {% set selection = selection|merge({(attribute.name): selected}) %}
{% endfor %}

{# 
  NOTE: The "variantAttributes" below in this example should be the handle of the
  Variant Attributes field you created and have added to your variant fields layout
#}
{% set variant = craft.variants().productId(productId).variantAttributes(selection).one() %}

<h1>{{ product.title }}</h1>
{% if variant is not null %}
  <h2>{{ variant.sku }} - {{ variant.price|commerceCurrency }}</h2>
{% endif %}

<div>
  {% for attribute in attributeOptions %}
    <div>
      <label>
        {{ attribute.name }}
        <select name="attributeValue_{{ loop.index }}" @change="attributeChanged">
          {% for value in attribute.values %}
            <option value="{{ value }}" {{ selection[attribute.name] == value ? 'selected' }}>{{ value }}</option>
          {% endfor %}
        </select>
      </label>
    </div>
  {% endfor %}
</div>

{% if variant is not null %}
  <form sprig s-method="post" s-action="commerce/cart/update-cart">
    <input type="hidden" name="purchasableId" value="{{ variant.id }}">
    <input type="submit" value="Add to cart">
  </form>
{% else %}
  <p>No matching variant found</p>
{% endif %}

{% if success is defined %}
  {{ success ? flashes.notice : flashes.error }}
{% endif %}


{% js %}
  function attributeChanged(e) {
    let queryParams = new URLSearchParams(window.location.search)

    queryParams.set(e.target.name, e.target.value);
    window.location.search = queryParams.toString()
  }
{% endjs %}

We can take it from here.

We take on the Craft and Craft Commerce sites you built, so you can get back to building. Introduce a client who signs a management contract and you get a $3,000 partnership fee.

How the Dev Partnership Program works
See if we’re a fit