d
Topic
Posts:
1
August 05, 2008

List all Types in a Collection without duplicates This post is outdated

I'm trying to get a hyperlink list of all types within a collection. It seems this could be done by looping through all products, for each product create a link using its type only if it has a new type (thereby eliminating a single type being repeated once or more). The question is, how do I do that? One approach is to create an array that would hold all the types that have appeared in the collection at any given iteration, and compare the current iteration (product type) against all types in the array. Can you create arrays? If you can't you could probably put all types in a string variable while separating each type with a special character like an underscore. Then you would need to access the String objects indexOf and subStr methods, do those exist? This is all I have so far that successfully outputs a list of types each as a hyperlink for a single collection.

i
Replies
Posts:
116
August 08, 2008

here’s some code that works pretty well for me. the one downfall of this method is that if products in the collection aren’t ordered by type, then you get some duplicates. for example if the first product is type A second is type B and third is type A, then type A will show up twice.

If liquid had the ability to create arrays it would be easy, but it doesn’t (someone patch that!)

Anyway, here is my code:

<ul class="rightlinks">
   {% assign: product_type = "none" %}
      {% for product in collection.products %}
    {% if product_type != product.type %}
       <li>{{ product.type | link_to_type }}</li>
       {% assign: product_type = product.type %}
        {% endif %}
     {% endfor %}
</ul>
Owner, Velocis Enterprises LLC www.velocisenterprises.com We Build Custom Shopify Themes http://www.velocis.us/shopify.php
Posts:
3
September 02, 2008

Kids, I’ve got some good news. I’ve managed to string together a method that can loop through any collection and skip duplicates, independently of the ordering. With future upgrades to liquid (i.e. concatenation operator for variables, ability to use filters within {% %} tags, etc.) the code would look simpler.

Basically, as you loop through, a string containing all product types is created. each product type is checked against it – if the type is found in the list, that means it’s been output already.

Say the complete list of types returned is:
beds,sofas,tables,beds

This is what happens:

        list before pass     Type    print it?  After pass  
pass1:  ,                    beds    Yes        ,beds,
pass2:  ,beds,               sofas   yes        ,beds,sofas,
pass3:  ,beds,sofas,         tables  yes        ,beds,sofas,tables,
pass4:  ,beds,sofas,tables,  beds    no         ,beds,sofas,tables,

At each pass, the code tries to replace the type (e.g.’,beds,’) with ’’ in the list. if this is successful, the product list is now shorter (i.e. sofas,tables,). I then compare it with the list as it was before the pass to know if I have a hit. if I don’t have a hit, I can add the type to the list.

code:

{% assign typeList = ',' %}
{% for product in collections['collectionName'].all_products %}
    {% capture sizeCheck %}{{typeList | size}}{% endcapture %}
            {% if sizeCheck == '1' %}
                    {% capture temp %},{{product.type}},{% endcapture %}
                    {% assign typeList = temp %}
                    <li>{{ product.type | link_to_type }}</li>
                {% else %}
                    {% capture compareType %},{{product.type}},{% endcapture %}
                    {% capture compareListSize %}{{typeList | replace: compareType, '' | size }}{% endcapture %}
                    {% capture typeListSize %}{{typeList | size}}{% endcapture %}
                    {% if compareListSize == typeListSize %}
                        <li>{{ product.type | link_to_type }}</li>
                            {% capture tempList %}{{typeList}}{{product.type}},{% endcapture %}
                        {% assign typeList = tempList %}
                        {% endif %}
    {% endif %}
{% endfor %}

Try it out, the same approach should work with any other collection.

hope this helps.


Olivier Dumetz
VP, OLA Interactive Agency
www.olaisred.com

Posts:
3
September 04, 2008

Well – I did not realise there was a “contains” operator. makes things a lot more simple. here is the updated code.

{% assign typeList = ',' %}
{% for product in collections['collectionName'].all_products %}
     {% capture compareType %},{{product.type}},{% endcapture %}
        {% if typeList contains compareType %}{% else %}
               <li>{{ product.type | link_to_type }}</li>
               {% capture tempList %}{{typeList}}{{product.type}},{% endcapture %}
               {% assign typeList = tempList %}
    {% endif %}
{% endfor %}


Olivier Dumetz
VP, OLA Interactive Agency
www.olaisred.com

Posts:
116
September 04, 2008

Oliver, good stuff!!

I see the capture class in the liquid documentation but there is no explanation as to what it does or how it functions. Can you elaborate on that?

Owner, Velocis Enterprises LLC www.velocisenterprises.com We Build Custom Shopify Themes http://www.velocis.us/shopify.php
Posts:
150
September 04, 2008

capture works like assign, but is often more powerful, because you can generate a user variable based on liquid output + basic strings, etc.

And this is very handy, by the way. Thanks Oliver!

Matt Beck, CouldBe Studios | Portland, OR | http://www.couldbestudios.com : http://deals.couldbestudios.com
Posts:
5778
Last edited September 05, 2008

Merci, Olivier, that’s very clever!

Caroline from http://11heavens.com ∴ mllegeorgesand AT gmail DOT com
Jamie Chief Officer of Funness shopify.com/plus
Posts:
5854
Last edited May 18, 2011

That's good stuff!

http://evolvedesign.co ::: http://twitter.com/bacchus
Renobird Member
Posts:
9
Last edited September 18, 2008

Hello,

I’m trying to implement Olivier’s code above, but I’m getting this error:

Liquid error: undefined method `to_liquid' for CollectionDrop:Class

Here’s my exact code below – any help would be much appreciated – I’m new to shopify/liquid and a bit out of my depth. ; )

<h3>Accessories</h3>
      <ul id="links">

{% assign typeList = ',' %}
{% for product in collections['Accessories'].all_products %}
     {% capture compareType %},{{product.type}},{% endcapture %}
        {% if typeList contains compareType %}{% else %}
               <li>{{ product.type | link_to_type }}</li>
               {% capture tempList %}{{typeList}}{{product.type}},{% endcapture %}
               {% assign typeList = tempList %}
    {% endif %}
{% endfor %}
</ul>
Posts:
5778
September 17, 2008

Well for one thing you use the keyword ‘for’ twice.

Caroline from http://11heavens.com ∴ mllegeorgesand AT gmail DOT com
Renobird Member
Posts:
9
Last edited September 18, 2008

Nice catch Caroline. :)

That was a copy/paste error when I was posting to the forum…I accidentally deleted the first few lines and had to retype…must have had butter on my fingers. Fixed it in my original post.

Anyhow, I just double checked, and the code in my page doesn’t have the duplicate “for”. I still haven’t had any luck fixing the error.

Any ideas?

Posts:
5778
September 18, 2008

The collection name should be the handle I think. No capital letter.

Caroline from http://11heavens.com ∴ mllegeorgesand AT gmail DOT com
Posts:
5778
Last edited September 18, 2008

Yes it has to be the handle…

Provided ‘accessories’ is the handle…

{% for product in collections['accessories'].all_products %}

Or

{% for product in collections.accessories.all_products %}

Since Liquid is not recognizing what you give it as the name of a collection or the name of any other ‘property’ of collections, it just tells you so…

Liquid error: undefined method `to_liquid' for CollectionDrop:Class

http://wiki.shopify.com/Collections

Caroline from http://11heavens.com ∴ mllegeorgesand AT gmail DOT com
Renobird Member
Posts:
9
September 18, 2008

Yep. That was it. Thank you so much for the help.
This little bit of code is pretty sweet!

Cheers!

Tom

Renobird Member
Posts:
9
September 18, 2008

Question about a variation of this:

What if I wanted to create a table (instead of list) of just the first image of the first product for each type?

I figured out how to get the first image by using:

<a href="{{ product.url | within: collection }}" 
title="{{ product.title }} &mdash; {{ product.description |
strip_html | truncate: 50 }}"><img src="{{
product.images.first | product_img_url: 'small' }}" alt="{{
product.title }}" /></a>

instead of:

{{ product.type | link_to_type }}

But I’m not sure how to get it all into a table.
I tried using

tablerow
– but I couldn’t figure out how to incorporate it.

Any help would be appreciated.

Renobird Member
Posts:
9
September 19, 2008

Hello All,

I’m still pounding my head against the desk with this one.
Anyone have time to take a quick look and help me with the above post?

I’m not a programmer, and I’ve just starting using liquid, so I know I’m in over my head. : )

Cheers!

Tom

Posts:
5778
Last edited September 19, 2008

Why do you want to use a table for this?

Using CSS you can style your list so that images will be side by side with x images per ‘row’. With the right amount of margin you want.

You cannot use tablerow in this particular case. This falls into the category of “will produce swiss cheese table”.

Just write your own markup.

If one image per row, you go…

<h3>Accessories</h3>
<table id="links">
{% assign typeList = ',' %}
{% for product in collections['accessories'].all_products %}
  {% capture compareType %},{{product.type}},{% endcapture %}
  {% if typeList contains compareType %}{% else %}
  <tr><td><a href="{{ product.url | within: collection }}" 
title="{{ product.title }} &mdash; {{ product.description |
strip_html | truncate: 50 }}"><img src="{{
product.images.first | product_img_url: 'small' }}" alt="{{
product.title }}" /></a></td><tr>
  {% capture tempList %}{{typeList}}{{product.type}},{% endcapture %}
  {% assign typeList = tempList %}
  {% endif %}
{% endfor %}
</table>
Caroline from http://11heavens.com ∴ mllegeorgesand AT gmail DOT com
Renobird Member
Posts:
9
September 19, 2008

Thank You Caroline! You’re definitely right about the “swiss cheese table” – that was the only result I could get.

I guess there was no reason to use tablerow – other than I found an collection.liquid page someone else made that used tablerow – so I though it might be a good method. Usually I wouldn’t even consider tables for this.

Thanks again for the help. Much appreciated.

: )

Posts:
5778
September 19, 2008

You are welcome :-)

Caroline from http://11heavens.com ∴ mllegeorgesand AT gmail DOT com
Joanne Member
Posts:
36
September 19, 2008

I wish I had a clue as to what any of that means! :(

Renobird Member
Posts:
9
September 22, 2008

Joanne,

Does it sound like something that would be useful to you?

If so, I can help you understand the basics of why you might want the above code – although I’m very much still learning myself.

Say you have a collection of products called “Shirts”.

In that collection you have several product-types “Men, Women, Kids, Babies”. Each of those product-types could have a lot of products assigned to them.

The code that _oli_ posted will allow you to create a link-list of all the product types in the collection. (in this case, “Shirts”)

So in your theme.liquid page the code will produce a list like this:

<h3>Shirts</h3> // You need to add this before the code
<ul class="links">// You need to add this before the code

//This is what _oli_'s code creates
<li><a href="/link/to/type">Men</a></li>
<li><a href="/link/to/type">Women</a></li>
<li><a href="/link/to/type">Kids</a></li>
<li><a href="/link/to/type">Babies</a></li>

</ul> // You need to add this after the code.

Hope that helps – someone please correct me if I explained that wrong or left anything out. My understanding of what’s going on is fragile at best. ; )

Posts:
150
September 29, 2008

I just have to point out here that these and many other things rely on all_products, which is actually capped at the first 50 products.

So if you are trying to implement this for a larger shop, these sorts of solutions don’t really work unless you can reliably only iterate over collections with 50 or fewer products.

It’ll work GREAT for a lot of smaller shops though.

Matt Beck, CouldBe Studios | Portland, OR | http://www.couldbestudios.com : http://deals.couldbestudios.com
Posts:
49
Last edited March 02, 2009

On my default home page is the typical blurb about welcome to the site. I need to add a menu to help narrow a customers searches.

The code here is very interesting but I have more than 50 products! Multiple links to numerous categories/collections, each complete and each unique with no duplicates is what I need but thought there might be a simpler method.

I have 12 custom collections already each with x products but none have their own url as I can see?

Do I need to add the collections code to generate the links or can I create a simpler link to each existing Custom Collection? How do I create a link to a collection using custom collections, isn’t that what it’s for?

Jamie Chief Officer of Funness shopify.com/plus
Posts:
5854
March 03, 2009

Sounds like you need to make a simple collection.

See wiki

and Here

To get directly to your collection simply add the handleized name behind collections like so:

/collections/my_custom_collection

http://evolvedesign.co ::: http://twitter.com/bacchus
Posts:
37
July 13, 2011

Can this be done with product variants as well? If so, how? I tried switching product.type for variant.option1 but that wont work.

Log in or sign up for an account to reply.

This thread has been closed! You will not be able to reply.