I have a Jekyll site with a collection, colleges, that I want to sort and display by a custom rankings front matter attribute. Here is an example of items in the collection:
---
title: Example College
score: 88
rankings:
- top accredited colleges
- most affordable
---
...
---
title: Sample College
score: 75
rankings:
- most affordable
- best online programs
---
...
---
title: Example University
score: 75
rankings:
- top accredited colleges
- best online programs
---
I would like to display the different rankings as headings with the colleges listed under them like so:
top accredited colleges
- Example College
- Example University
most affordable
- Example College
- Sample College
best online programs
- Sample College
- Example University
I've tried using Liquid's group_by filter like so:
{% assign groups = site.colleges | group_by: "rankings" %}
{% for group in groups %}
<h2>{{ group.name }}</h2>
<ul>
{% for college in group.items %}
<li>{{ college.title }}</li>
{% endfor %}
</ul>
{% endfor %}
But this seems to group the rankings front matter by an exact match of the full array rather than separating out the different values it contains:
<h2>[top accredited colleges, most affordable]</h2>
<ul>
<li>Example College</li>
</ul>
<h2>[most affordable, best online programs]</h2>
<ul>
<li>Sample College</li>
</ul>
<!-- etc -->
How do I separate out the individual values from the rankings front matter array in the output?
This can do the trick :
{% assign allRankings = site.colleges | map: "rankings" %}
{% assign rankingArray = "" | split:"" %}
{% for rankings in allRankings %}
{% assign rankingArray = rankingArray | concat: rankings | uniq %}
{% endfor %}
{% for ranking in rankingArray %}
<h2>{{ ranking | capitalize }}</h2>
<ul>
{% for college in site.colleges %}
{% if college.rankings contains ranking %}
<li>{{ college.title }}</li>
{% endif %}
{% endfor %}
</ul>
{% endfor %}
Related
I'm using Eleventy and have created the subfolder yummy in my global data folder, that contains the following files:
\src\_data\yummy\drinks.json
\src\_data\yummy\food.json
When I use {{ yummy | dump }} I get the following output:
{"drinks":[{"name":"Milk","price":5},{"name":"Water","price":1}],"food":[{"name":"Pizza","price":4},{"name":"Hot dog","price":2},{"name":"Sallad","price":1},{"name":"Avocado","price":3}]}
I want to create a list with all entries in both json-files. I almost have achieved this with the following loop:
<ul>
{% for key, val in yummy %}
<li>{{ val[0].name }} cost {{ val[0].price }}$</li>
{% endfor %}
</ul>
However, since I'm using [0], the output is only the first entry in each json-file:
- Milk cost 5$
- Pizza cost 4$
I want all entries and have tried the following, but get no output at all:
<ul>
{% for key, val in yummy %}
<li>{{ val[key].name }} cost {{ val[key].price }}$</li>
{% endfor %}
</ul>
Managed to solve this myself by adding a second loop.
<ul>
{% for key, val in yummy %}
{% for entry in val %}
<li>{{ entry.name }} cost {{ entry.price }}$</li>
{% endfor %}
{% endfor %}
</ul>
Outputs as:
- Milk cost 5$
- Water cost 1$
- Pizza cost 4$
- Hot dog cost 2$
- Sallad cost 1$
- Avocado cost 3$
I have a data files with different items. Each item have nested tasks. I am trying to loop the nested tasks and present each task by the task type.
YML DATA
- name: Outside
description: Description
tasks:
- type: Food
name: Eat it outside
status: working
- type: Drinks
name: Drink it outside
status: working
- name: Inside
description: Description
tasks:
- type: Food
name: Eat it inside
status: pending
- type: Drinks
name: Drink it inside
status: working
Liquid
{% for item in site.data.info %}
{% assign grouped-tasks-by-type = item.tasks | group_by: "type" %}
{% for task in grouped-tasks-by-type %}
<h2 class="task-type">{{ task.type }}</h2>
<ul>
{% for task in item.tasks %}
{% if task.status == 'working' %}
<li>{{ item.name }}: {{ task.name }}</li>
{% endif %}
{% endfor %}
</ul>
{% endfor %}
{% endfor %}
Expected result (HTML)
<h2 class="task-type">Food</h2>
<ul>
<li>Outside: Eat it outside<li>
</ul>
<h2 class="task-type">Drinks</h2>
<ul>
<li>Outside: Drink it outside<li>
<li>Inside: Drink it inside<li>
</ul>
However, I am getting a full blank result. Is this possible to do with group_by?
I hope my algorithm below serves you well. I was able to achieve your expect end result with the algorithm. I was unable to utilize the group_by in my solution. The sample code contains Liquid comment blocks to explain my thought process.
Testing
I used the minima git repo, with command jekyll s. I placed your YML data in a file with path _data/info.yml in my locally cloned minima git repo. I used post.html as the code sandbox.
You can print out the Liquid variables to the DOM by doing {{ all_food_types | json }} in the code.
Solution
{%- comment -%}
End Goal: Find all the food types for <h2>.
1. Use map: "tasks" to gather all the tasks into a single array.
This will cause the loss of Outside/Inside information for each task
2. Use map: "type" to create a list of food types ("Food", "Drinks")
3. Use uniq to remove duplicate food types from the array
{%- endcomment -%}
{% assign all_food_types = site.data.info | map: "tasks" | map: "type" | uniq %}
{%- comment -%}
End Goal: Loop through all the data looking
for a specific food type (Food, Drinks)
and group them together
{%- endcomment -%}
{% for food_type in all_food_types %}
<h2 class="task-type">{{ food_type }}</h2>
<ul>
{% for item in site.data.info %}
{% for task in item.tasks %}
{% if task.status == 'working' and task.type == food_type %}
<li>{{ item.name }}: {{ task.name }}</li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
{% endfor %}
An aside, for whatever reason, my liquid ends up using a lot of arrays and for-loops.
Given a number of markdown files within an offices folder, I need to loop through each one and find/render the city value where the state is a given value. So far I have this, but it renders every city regardless of the where clause:
<ul class="cities">
{% for post in site.offices | where: "state", "florida" %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
<li>{{ post.title }}</li should list all of the cities from the markdown files that have Florida as their state.
This is a sample markdown file:
---
office_id: 5
title: Orlando
state: florida
phone: 123-456-7890
---
I discovered that I had to set an assignment first:
{% assign cities = (site.offices | where: "state" , "florida") %}
{% for city in cities %}
<li>{{ city.title }}</li>
{% endfor %}
I am working on a Jekyll project. This is a blog with posts which have categories.
I would like to succeed in having a sidebar on the right side listing the categories and the count of posts related to this category AND when clicking on the category itself, having the list of the posts related to this category.
For now, I succeeded in having the list of categories with their counts but not the display of the posts. Here is the code :
<ul class="tag-box inline">
{% assign tags_list = site.categories %}
{% if tags_list.first[0] == null %}
{% for tag in tags_list %}
{{ tag | capitalize }} <span>{{ site.tags[tag].size }}</span>
{% endfor %}
{% else %}
{% for tag in tags_list %}
<div>{{ tag[0] | capitalize }} <span> ({{ tag[1].size }}) </span></div>
{% endfor %}
{% endif %}
{% assign tags_list = nil %}
</ul>
I was looking for some solutions on Internet and some of them were explaining that I should create a folder category and under this folder as many folder as categories I have with an index.html to display the categories. However, this is a lot of duplicated content and I don't know if it is the best way to do.
Thank you for your help!
As you cannot use plugins, you will have to create one page for each category.
In order to avoid repeating content, you can factorize with help of layout chaining. Your category pages will use category_index.html as layout, that will itself use default.html.
Sidebar
<ul class="tag-box inline">
{% for category in site.categories %}
<div>{{ category[0] | capitalize }} <span> ({{ category[1].size }}) </span></div>
{% endfor %}
</ul>
If you want urls like category/toto/ you have to set permalink: pretty in _config.yml.
A category page : category/toto.html
---
layout: category_index
category: toto
---
That's all.
_layouts/category_index.html
---
layout: default
---
<div class="home">
<h1 class="page-heading">Posts in category : {{ page.category }}</h1>
<ul class="post-list">
{% for p in site.categories[page.category] %}
<li>
<h2>{{ p.title }}</h2>
</li>
{% endfor %}
</ul>
</div>
I have a Jekyll app (using Liquid) and I'd like to know how to, in Liquid, group a collection of items into a small subset of collections.
For instance, pretend I have this array:
fruits = ['apples', 'oranges', 'bananas', 'pears', 'grapes']
What I'd really like to do, in the Liquid page, is get this:
fruit_groups = [['apples', 'oranges'], ['bananas', 'pears'], ['grapes', null]]
For example, Ruby on Rails can do this with their .group_by method attached to enumerables.
Can I do this in Liquid?
Use case: I have a big collection of items, but I need to convert them into columns of <ul> elements. So, if I have three columns, I need to get three sub-collections.
Thanks!
This doesn't answer your question directly, but I'm not sure that you'd want to do what you're describing (and I'm pretty sure you can't) - Liquid is a templating system, not a fully fledged programming language. I suspect that you'll be able to achieve your end goal using some of the for loop and cycle features: http://code.google.com/p/liquid-markup/wiki/UsingLiquidTemplates
eg:
<ul>
{% for fruit in fruits %}
{% capture pattern %}{% cycle 'odd_class', 'even_class' %}{% endcapture %}
<li class={{ pattern }}>{{ fruit }}</li>
{% endfor %}
</ul>
or
<ul class="odd">
{% for fruit in fruits %}
{% capture pattern %}{% cycle 'odd', 'even' %}{% endcapture %}
{% if pattern == 'odd' %}
<li>{{ fruit }}</li>
{% endif%}
{% endfor %}
</ul>
<ul class="even">
{% for item in fruits %}
{% capture pattern %}{% cycle 'odd', 'even' %}{% endcapture %}
{% if pattern == 'even' %}
<li>{{ fruit }}</li>
{% endif%}
{% endfor %}
</ul>
If you have three columns, you'd just have three steps in your cycle, and three directions to go in your if statement.
If all that fails, you could write a plugin (in Ruby) that will restructure your data before it ever hits the template layer, but I suspect that would be overkill.