Page variable name in for loop using data files

Hi,

Looking for some help on using dynamic variable names within data file locations. I can’t seem to get things working.

Firstly, here is my structure for context (my data_dir is docs):

docs/
├─ users/
│  ├─ general/
│  │  ├─ users.md
│  ├─ config.json

I currently have this loop working fine as the data file location is hard coded:

## Table of contents
<ul>
{% for query in site.data.users.config %}
  <li>
    <a href="#{{ query.name | downcase | replace: " ", "-"}}">
      {{ query.name }}
    </a>
  </li>
{% endfor %}
</ul>

However, I’m trying to essentially get from this:

{% for query in site.data.users.config %}

to something like this using the parent front matter variable:

---
parent: Users
---
{% for query in parent.config %}

I’ve tried this which did not work: {% assign x site.data.{{ parent | downcase }} %} and using x.config

If I print out the x variable above then I do start to get ```{“users”=>{“config”=>[{``…`

I’m at a bit of a loss for how to proceed. Any help would be much appreciated!

did you try site.data.page.parent.config or maybe more likely site.data.{{page.parent}}.config?

Thanks for the suggestion! Unfortunately I tried both and neither worked :pensive:

When you type site.data.xxx, you are telling Jekyll "go to the site root, go to the _data folder, and get the following data file from there. Ideally, you would probably like to type site.docs.users/config. However, I am not aware of a way to put a data file in any location other than the _data folder.

Move your _config.json file to /_data/config.json and then call the code with site.data.config. You could also put it under a /_data/users/config.json folder structure and then call it with site.data.users.config. Personally, I try to avoid multiple folder structures for my data unless I plan on creating a very large number of them. For that reason, I would probably call the file /_data/user-configs.json

If you do not have a _data folder at the root of your Jekyll folder, create one and Jekyll will automatically know how to handle it.

Your new docs folder structure will look like this:

docs/
├─ users/
│  ├─ general/
│  │  ├─ users.md

Use (or create) the _data folder at the root of your Jekyll folder

/_data/
├─ user-config.json

Your code will now look like this

## Table of contents
<ul>
{% for query in site.data.user-config %}
  <li>
    <a href="#{{ query.name | downcase | replace: " ", "-"}}">
      {{ query.name }}
    </a>
  </li>
{% endfor %}
</ul>

Of course, if you want to keep a similar structure, you could do the following

Use (or create) the _data folder at the root of your Jekyll folder

/_data/
├─ users/
│  ├─ configs.json

Your code will now look like this

## Table of contents
<ul>
{% for query in site.data.users.configs %}
  <li>
    <a href="#{{ query.name | downcase | replace: " ", "-"}}">
      {{ query.name }}
    </a>
  </li>
{% endfor %}
</ul>

Here is the official documentation for your reference

Hi Bill,

Thanks for your response!

I have site.data.users.configs working out of my docs folder (by setting data_dir: docs in _config.yml), but what I’m looking to do is have a more dynamic way to replace the part between data and configs based on front matter on the page itself.

So I would ideally have front matter like this for my files page:

---
parent: files
---

And site.data.{{ parent }}.configs would turn into site.data.files.configs automatically, but that is not happening right now, even if I specify site.data.{{ page.parent }}.configs.

I’ve also tried something like the below but it hasn’t worked:

{% assign parent = "users" %}
<ul>
{% for query in site.data.{{ parent }}.configs %}
.....

try site.data.parent.configs - no curly braces but with the assignment. (is it config or configs?)

I would make a simpler example in your data directory just to minimize the number of things involved. My guess is you can do what you want you just have to find the correct format.

Ah! Okay, I completely misunderstood your question, so let’s try that again :slight_smile:

That said, I am unsure what you are looking to do as your code examples are a little confusing, but I am hopefully getting what you want based on the following two answers.

Option #1: Get a specific data file based on the YAML front matter

In this example, you dynamically access a data file based on a variable you define in the front matter. For example, you want to get the list of items in a JSON file located at site.data.configs.items.

page.markdown yaml front matter

---
parent: configs
---

Code

{% assign myData = site.data[page.parent].items %}

{% for data in myData %}
  your code...
{% endfor %}

The assign tag will create the myData data source dynamically based on what you put in the parent yaml front matter. Note that you do not put a . (period/dot) between data and [page.parent] or that will result in a warning from Jekyll.

Option #2: Filter data based on YAML front matter

In this example, you have the hard-coded data source, but you want to filter the data based on something listed in the front matter.

page.markdown yaml front matter

---
filter: title
---

Code

{% assign myData = site.data.configs.items | where_exp: 'item', 'item.title == page.filter' %}

{% for data in myData %}
  your code...
{% endfor %}

I hope that helps!

edit: changed where to where_exp

Option 1 worked and is perfect for what I’m trying to do! Thanks so much Bill!!

Sorry for the confusion around data structure, I’m essentially trying to have as few areas to maintain files as possible (this is for an internal wiki).

Q on [page.parent] - are square brackets required because items within data are in an array or is this just the notation for pulling a page variable?

You are very welcome! Honestly I’m not sure why the square brackets as I came across a similar need before and had the solution handy :slight_smile: