6

In my front matter for some pages (not all) I have:

---
top-navigation:
    order: 2
---

Using liquid I want to filter all site pages which have a top-navigation object and sort by top-navigation.order.

I'm trying sort:'top-navigation.order' but that's throwing an exception of undefined method [] for nil:NilClass. I tried where:"top-navigation", true but it's not equating truthy values.

How can I filter for pages that have top-navigation and then sort?

marcanuy
  • 23,118
  • 9
  • 64
  • 113
Kurren
  • 827
  • 1
  • 9
  • 18

2 Answers2

6

Two steps:

  1. Create an array with pages that contains the top-navigation key.

    We create an empty array and then push the items that have the key.

    {% assign navposts = ''|split:''%}
    {% for post in site.posts %}
    {% if post.top-navigation %}
    {% assign navposts = navposts|push:post%}
    {% endif %}
    {% endfor %}
    
  2. Sort the above array by top-navigation.order

    {% assign navposts = navposts|sort: "top-navigation.order"%}
    

Printing results:

{% for post in navposts %}
<br>{{ post.title }} - {{post.top-navigation}}
{% endfor %}

For pages use site.pages.

marcanuy
  • 23,118
  • 9
  • 64
  • 113
  • this works very well. I even added a uniq filter on it for my tag list. – Edward Nov 27 '17 at 21:55
  • ended up here after reading the jekyll filter list. There's a "where: nil" filter , available starting from v4.0.0 ([docs](https://jekyllrb.com/docs/liquid/filters/#detecting-nil-values-with-where-filter400)). Wasn't sure how to get the converse filter. This answer seems more portable anyway. – init_js Jun 20 '19 at 21:43
5

In Jekyll 3.2.0+ (and Github Pages) you can use the where_exp filter like so:

{% assign posts_with_nav = site.posts | where_exp: "post", "post.top-navigation" %}

Here, for each item in site.posts, we bind it to the 'post' variable and then evaluate the expression 'post.top-navigation'. If it evaluates truthy, then it will be selected.

Then, putting it together with the sorting, you'd have this:

{%
  assign sorted_posts_with_nav = site.posts 
  | where_exp: "post", "post.top-navigation" 
  | sort: "top-navigation.order"
%}

Liquid also has the where filter which, when you don't give it a target value, selects all elements with a truthy value for that property:

{% assign posts_with_nav = site.posts | where: "top-navigation" %}

Unfortunately, this variant does not work with Jekyll.

Jared Khan
  • 333
  • 2
  • 12