IWI
IWI

Reputation: 1608

Shopify: How to check if there is > 1 collection in a cart

I am trying to prevent orders with more than one collection from being checked out. If there's more than one collection, i just want to disable the checkout button. I know the syntax is bad, but i want to do something like this.

{% for item in cart.collections %}
 {% if item.collection.length > 1 %}
    <button disabled>Cant checkout</button>
  {% else %}
    <button disabled>Can checkout</button>
  {% endif %}

This is the current code for the button

<div class="cart__checkout-wrapper">
        <button disabled id="button" type="submit" name="checkout" data-terms-required="{{ settings.cart_terms_conditions_enable }}" class="btn cart__checkout">
          {{ 'cart.general.checkout' | t }}
        </button>

        {% if additional_checkout_buttons and settings.cart_additional_buttons %}
          <div class="additional-checkout-buttons additional-checkout-buttons--vertical">{{ content_for_additional_checkout_buttons }}</div>
        {% endif %}
      </div>
{% endfor %}

Upvotes: 0

Views: 989

Answers (1)

Dave B
Dave B

Reputation: 3248

Method 1

This simple check might work for what you need:

{% liquid 
  assign all_collections_in_cart = cart.items | map: 'product' | map: 'collections' | map: 'title' | uniq
  assign collection_count = all_collections_in_cart.size

  if collection_count > 1
    assign can_checkout = false
  else
    assign can_checkout = true
  endif
%}

What it does

First, we use a sequence of map filters to 'drill down' through the object structure. Items in the cart do not themselves belong to any specific collection(s), but each item is associated with both a variant and a product. From the product, we can then get all of the collections that it belongs to, which will be an array of collection objects. We can't do much with the objects themselves, so we drill down one layer further to get something that can be compared, such as title handle or id. At this point we now have an array of text entries (or numbers, if you swap to IDs), so we can apply the uniq filter to remove any duplicates.

Now that we have an array with no duplicates, we can check the size of the array to see if it is greater than one and set a variable appropriately.

Note that this will always return false if a single product belongs to more than one collection!


Method 2:

If instead you need to test that all products share a collection because products can belong to more than one at a time, we won't be able to take as many shortcuts. Instead, our code might look something like this:

{% liquid
  assign can_checkout = true

  if cart.items.size > 1
    assign shared_collections = cart.items.first.product.collections | map: 'title'
    for item in cart.items
      if forloop.first
        continue
      endif
      assign item_collections = item.product.collections | map: title

      assign placeholder_array = ''
      for coll in shared_collections
        if item_collections contains coll
          if placeholder_array.size > 0
            assign placeholder_array = placeholder_array | append: ','
          endif
          assign placeholder_array = placeholder_array | append: coll
        endif
      endfor
      assign shared_collections = placeholder_array | split: ','
      if shared_collections.size == 0
        assign can_checkout = false
        break
      endif
    endfor
  endif
%}

What it does

This second version will trigger if there are 2 or more items in the cart. If there are, we get all of the collection titles from the first item in the cart, then loop through all of the remaining items in the cart. At each step, we go through our list of shared collections to see how many are shared with the current item in the cart to make a new array. (Liquid does not let us make an array directly, so we have to build out a delimited string and then use the split filter afterwards)

If at any time we have an array with 0 shared entries, we set our can_checkout variable to false and use the break command to stop searching.


Addendum

For both of the above methods, things might get a little bit trickier if you have certain collections that don't count towards your collection rules. For example, if you have 'featured' or 'summer sale' collections, you will want to make sure that you aren't counting those in the collection comparisons (for example, by having an array of exceptions and removing those items from the array of collections that the item belongs to).

Upvotes: 3

Related Questions