hallowedhollow
hallowedhollow

Reputation: 13

Jekyll front matter variable to dynamic navigation?

So I'm pretty new to jekyll and liquid in general, and I did some searching and couldn't find a concrete answer to my issue.

So basically, I'm making a jekyll site that needs to be as easy for contributors as possible, as there is not just one site contributor. With that in mind, I'm wondering if it is possible to make a dynamic navigation on build that would take a custom variable on a page's front matter and, if it matches a top level navigation item (amount won't be changing), put the page link in a dropdown for said navigation item.

As an example, let's say I have top level navigation items: Color and Animal. If a contributor wants to add a page called 'Duck', he could just put in his front matter

parent: Animal
permalink: duck

and, upon build, jekyll will go through each page, and when it happens upon page 'duck' it will put the link into the Animal navigation item as a dropdown menu.

I know there are others ways to make multi-level navigations, as described in the Jekyll documentation, but those would require somebody to change the configuration file each time, unless I completely misunderstand it. I would like for a contributor to just have to worry about the page he's making, and I think the front-matter is a good place to do it.

Edit: I'm going to supply what I've tried already although, I think my code will make you laugh because it's probably way off and maybe way overcomplicated. The following code assumes a navigation array in config for the top level items with 'text' and 'url' variables. Not all will have links and may only serve as dropdowns. It also assumes a variable on the page called 'parent-text' which is where the matching will happen.

{% for link in site.navigation %} <a href="{{link.url}}">{{link.text}}</a> 

{% for page in site.pages %}

{% if page.parent-text == true %}

<a href="{{page.permalink}}"> {{page.parent-text}} </a>

{% endif %}

{% endfor %}

{% endfor %}

I'm just trying to get it to output. I'll handle the styling and markup later.

Thanks everyone in advance!

Upvotes: 1

Views: 902

Answers (1)

dawaltco
dawaltco

Reputation: 346

The first thing I'd say is to be careful with using page as a variable in your loops. page has special meaning for Jekyll (docs) and setting it in a loop or as a variable will override how it usually works.

Using Front Matter

I'm a little confused by your example and why you're checking that page.parent-text == true. This only checks that the file in question has front matter with some key parent-text, which is not set to false. It seems like you want to compare it to the text of the navigation link. Something like this should work:

{% for link in site.navigation %}
  <a href="{{link.url}}">{{link.text}}</a>
  {% for my_page in site.pages %}
    {% if my_page.parent == link.text %}
      <a href="{{page.permalink}}"> {{page.title}} </a>
    {% endif %}
  {% endfor %}
{% endfor %}

Using a Data File

You could also use a data file. Say you have a file, _data/nav-links.yml, which looks like this:

- text: Animals
  url: '/animals/'
  dropdown:
    - text: Duck
      url: '/duck/'
    - text: Goose
      url: '/goose/'

And then, in your nav, you have:

{% for link in site.data.nav-links %}
  <a href="{{ link.url }}">{{ link.text }}</a>
  {% for sub_link in link.dropdown %}
    <a href="{{ sub_link.url }}">{{ sub_link.text }}</a>
  {% endfor %}
{% endfor %}

This isolates the relevant information into its own file, so contributors don't have to sift through this config. This is preferable if you think there is any chance the names of the links in site.navigation will change; if any of them did, then all of the corresponding parent or parent-text variables in the front matter of all the relevant pages would also have to change.

Upvotes: 3

Related Questions