Load a range of Pages (Params / Frontmatter) into a Javascript as Data

Currently, I am reading in data into a javascript with the following:

let locations = {{ .Site.Data.network.members }}

and everything works fine.

However, I would like to make these into webpages that people could visit - and still read this data into JS script and work with it like before. This has evaded me. I have tried several variations, the only one that doesn’t crash Hugo (so far) is:

let locations = {{ where .Site.Pages "Type" "network" }}

but the data doesn’t load - I get a JS error Uncaught TypeError: locations.reduce is not a function

But I all I did is tried to read in the data, I haven’t called any other step.

If someone can help me move forward that would be appreciative.

I can share my leaflet javascript if that helps.

The current data file looks like:

members:
  - name: Efeca
    description: >-
      Efeca, a Dorset based micro natural resources company, provides
      specialised consulting advice on responsible sourcing, sustainable trade
      and use of natural resources including palm oil, timber, soya, sugar and
      coffee. A Tropical Forest Alliance partner & World Economic Forum
      preferred supplier. Efeca has accumulated broad experience working in over
      30 countries, across agricultural and forest risk commodities.
    webSite: http://www.efeca.com
    email: lucy.cullinane@efeca.com
    image: /uploads/efeca.png
    group: Sustainability
    latitude: 50.7488
    longitude: -2.3445
    popupText: >-
      Efeca, a Dorset based micro natural resources company, provides
      specialised consulting advice on responsible sourcing, sustainable trade
      and use of natural resources including palm oil, timber, soya, sugar and
      coffee.

The new page / data source looks like:

---
title: Efeca
name: Efeca
type: network
webSite: http://www.efeca.com
email: lucy.cullinane@efeca.com
image: /uploads/efeca.png
group: Sustainability
latitude: 50.7488
longitude: -2.3445
popupText: >-
  Efeca, a Dorset based micro natural resources company, provides
  specialised consulting advice on responsible sourcing, sustainable trade
  and use of natural resources including palm oil, timber, soya, sugar and
  coffee.
---
Efeca, a Dorset based micro natural resources company, provides
specialised consulting advice on responsible sourcing, sustainable trade
and use of natural resources including palm oil, timber, soya, sugar and
coffee. A Tropical Forest Alliance partner & World Economic Forum
preferred supplier. Efeca has accumulated broad experience working in over
30 countries, across agricultural and forest risk commodities.

First, you need to change your front matter structure. I am assuming that each page represents a single member.

---
title: 'Efeca'
date: 2023-02-11T10:57:42-08:00
draft: false
type: network
member_data:
  name: Efeca
  webSite: http://www.efeca.com
  email: lucy.cullinane@efeca.com
  image: /uploads/efeca.png
  group: Sustainability
  latitude: 50.7488
  longitude: -2.3445
  popupText: >-
    Efeca, a Dorset based micro natural resources company, provides
    specialised consulting advice on responsible sourcing, sustainable trade
    and use of natural resources including palm oil, timber, soya, sugar and
    coffee.
---

Second, you need to build a slice of this data on your list/home page.

{{ $s := slice }}
{{ range where site.RegularPages "Type" "network" }}
  {{ $s = $s | append .Params.member_data }}
{{ end }}

<pre>{{ jsonify (dict "indent" "  ") $s }}</pre>

In a single page template you can do:

{{ with .Params.member_data }}
  <pre>{{ jsonify (dict "indent" "  ") . }}</pre>
{{ end }}

So I think I understand - I need to collect the data and write it to a file - ideally a json file (within Data?) and then I can load that into the json script with something like:

var locations = = {{ .Site.Data.network_data }}

to read the file data/network_data.json – how to I then write to a new file path? I don’t seem to find that in the docs.

Unfortunately, ever with the data in the format suggested I only get:

[
  null
]

Is there a way to debug this I need an arrary of arrays.

1 Like

You can only write to the public directory.

If the script is defined in the same template as the data collection…

some template

{{ $s := slice }}
{{ range where site.RegularPages "Type" "network" }}
  {{ $s = $s | append .Params.member_data }}
{{ end }}
{{ $d := jsonify $s }}

<script>
  const members = {{ $d }};
  console.log(members);
</script>

If the script is in your assets directory:

some template

{{ $s := slice }}
{{ range where site.RegularPages "Type" "network" }}
  {{ $s = $s | append .Params.member_data }}
{{ end }}
{{ $d := jsonify $s }}

<div id="foo" data-members="{{ $d }}"></div>

assets/main.js

document.addEventListener('DOMContentLoaded', function(event) {
  const el = document.getElementById('foo');
  if (el) {
    console.log(el.dataset.members)
  }
});

baseof.html

{{ with resources.Get "main.js" | js.Build }}
  <script src="{{ .RelPermalink }}"></script>
{{ end }}

Thanks!

It now works!

I was a little confused at first since in the debugger I didn’t notice that it was reading in the json as a string - I though it was reading in an array of Objects, like it did from the Data Files.

So with 2 minor tweeks:

  1. I had do do this for some reason outside my safeHTML
  2. I had to parse the json - obvious, but I didn’t notice at first I had a string instead of an array.
{{ "<!-- Feature Section Start -->" | safeHTML }}
<section>
  <div class="container">
    ...
  </div>
</section>
{{ "<!-- Feature Section End -->" | safeHTML }}

{{ $s := slice }}
{{ range where site.RegularPages "Type" "network" }}
{{ $s = $s | append .Params.member_data }}
{{ end }}
{{ $d := jsonify $s }}

<script>
  let network_json = {{ $d }};
  let locations = JSON.parse(network_json);
</script>

works the same as (except uses my new pages instead of my data file)! :slight_smile:

let locations = {{ .Site.Data.network.members }}

Hugo makes reading Data files simple and automatic - I didn’t appreciate that before.