1

I have spent ample time researching this without finding a solution that worked. I would love it if someone could help me figure this out.

I’m trying to use Dynamic Pages in my setup, but need to include dynamic Frontmatter with this. But I can’t use Frontmatter in the template file, so I was thinking I could use a YAML data file instead? I tried various approaches, but none were successful. The dynamic pages load just fine, but every one of them will use the same Frontmatter unless I can pull in dynamic data instead.

My config includes:

["england", "france"].each do |team|
  proxy "/teams/#{team}/index.html", "/teams/team.html", :locals => { :team_name => team }, :ignore => true
end

And my directory structure in this section looks like this:

teams
- index.html.erb
- team.html.erb

I began a YAML data file that includes:

england:
  title: "Teams/England"
  description: "England"
  headline: "England"
  addclass: "england cols"
france:
  title: "Teams/France"
  description: "France"
  headline: "France"
  addclass: "france cols"

When I use the aforementioned data in the template file as Frontmatter, it works just fine:

---
title: Teams/France
description: France
headline: France
addclass: france cols
---

One example of how I am using the data:

<%= current_page.data.addclass %>

My questions are as follows:

  1. How can I use a YAML data file to serve unique data to each Dynamic Page?
  2. Can I use the final URI segment ( “england” from /teams/england/, “france” from /teams/france/, etc.) to define which data set to use?
  3. Can I do this without impacting other non-dynamic-pages (/matches/, /groups/, etc.) on the site?

Thank you so very much in advance.

markwyner
  • 21
  • 2

1 Answers1

0

I'd suggest changing your data format slightly. It'll allow you to pass the entire local data item to the template so you can use the data without needing to first "load it" into Frontmatter.

Adjust your teams.yml file (I've added the 'slug' value here):

items:
- title: "England"
  slug: "england"
  description: "England"
  headline: "England"
  addclass: "england cols"
- title: "France"
  slug: "france"
  description: "France"
  headline: "France"
  addclass: "france cols"

Change your config.rb block to (assuming teams.yml is at /data/teams.yml) - note the check to prevent errors if data is missing:

if File.exist?("data/teams.yml")
  data.teams.items.each do |item|
     p = item
     proxy "teams/#{p.slug}.html", "teams/team.html", locals: { item: p }, ignore: true
  end
end

This will pass all the data from the team item into the template. You won't have to "define which data set to use", since the template context will refer just to that data item.

Now, in your team.html.erb template, you can reference the data like this (in the template body, not in the Frontmatter):

<h1 class="<%= item.addclass %>"><%= item.title %></h1>
<h2><%= item.description %></h2>
<h3><%= item.headline %></h3>

This should give you two separate pages for England and France with their own unique data.

Unfortunately, Frontmatter doesn't like to be overwritten after a dynamic page is generated in Middleman. For overwriting Frontmatter that you use for metadata, specifically "title", I've had success with gem 'middleman-meta-tags' [ https://github.com/tiste/middleman-meta-tags ] which allows you to override page titles in the template body after it's been defined, sourced from the YAML data.

Adam
  • 254
  • 2
  • 13
  • Yes! Adam, this is fantastic. Exactly what I was seeking. Thank you so much. I really appreciate that you took the time to explain this. It works great in a template, but not in a layout, where `item.x` isn't available on pages that aren't in the /teams/ directory. So, for example, in a layout I need to use something like `<% if current_page.url.start_with?('/teams') && current_page.url.split('/').last != 'teams' %>` to determine if it's a team page. Is there a more streamlined way to manage this? My solution works, but it's probably not the most efficient/clean. – markwyner Mar 11 '18 at 08:04
  • You could try using a separate layout per template type - Generally it's better to keep logic like that out of your template and use a helper rather than having a bunch of if statements in the template. I failed to mention above initially, but you can protect against missing data files by wrapping your dynamic page helper in an if 'File.exist?' - I've edited and added to above example. Checks like this could help you write a general helper for a single template to generate all your pages at once. – Adam Mar 12 '18 at 19:42
  • 1
    Yeah, that's a great point. I can create a separate layout, and then use partials to pull in the comment components. Thanks again, man. Super helpful. – markwyner Mar 13 '18 at 04:31