Is there a built-in way to create twig templates with custom JSON data?
Say I have JSON { "key": "value" }. There has to be a way to import it. My thinking is to include it with PHP, but maybe that's wrong. Then I should be able to write something like <div>{{key}}</div> to return value within the div. I know this can be done, I just wasn't sure if there was a so called intended way to do this with Grav or if this is not part of it.
I know I can generate my files and then load it with this plugin. I was just trying to see if there was a more direct way within Grav.
If my Data would be per-Page or per-Page-Tree I'd add it to the Frontmatter of the Page or the Head of the Pagetree, where it's applicable to.
I'd then use page.headers or page.parent.headers or a combination of page.find(…).headers to access it.
If the data is system-wide, you might put it into user/config/site.yaml and access it via site.my_variable.
You can also set theme-wide variables in user/config/themes/<theme>.yaml.
yes the 'built-in' way is to use YAML frontmatter to set your data, then simply json_encode it in Twig when you send it back via your .json.twig template. However, if your json needs to be maintained in json itself, the you would need a plugin to read it and set the json data as a Twig variable.
Awesome, thanks for taking the time to help answer my question. I'll look into it some more and if I decide to go the plugin route, then I may create one which seems beneficial to other Grav users, however, from just reading, I don't see why I can't use the Frontmatter. Thanks again.
@barryanders you can put the json in the frontmatter directly, like
---
title: 'Test'
json: {"glossary":{"title":"example glossary","GlossDiv":{"title":"S","GlossList":{"GlossEntry":{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":{"para":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML"]},"GlossSee":"markup"}}}}}
---
# test
and then create a yourpagetype.json.twig in the theme, and just have {{page.header.json|json_encode}} into it.
This will print the field content as JSON.
You need to |json_encode that field because JSON is interpreted by YAML, which means you can also write a YAML data structure in the header, and print it using |json_encode to build a JSON output.
Another way is to have the JSON in the page content directly. In that case, simply output {{ page.content }} in the json.twig file.
I finally got around to actually using this for a work project and I didn't realize that you could process twig directly in the content editor in Grav!. Seems pretty obvious now, but wow, that's such an amazing feature. Very useful. I can also see how it may be beneficial to have a plugin that reads json files separately rather than including them in frontmatter. I say this, because if I were to make, say, a mobile app that needs to access that same json data, I'm not sure how it would be accessible if it's tucked away in the frontmatter of a Grav page. I'm going to guess there's a way but I haven't looked too much into it yet.
Edit: Well, I see page-inject and file-content plugins don't seem to work for files from other websites. I think file-content will work nicely though. That way I can include it directly in my page, and still use the JSON for other purposes outside of Grav.
You can actually store data a number of ways.. you can put it in the frontmatter of a page, then 'find' that page, and then the header variable containing the data from wherever you want.
Or you can simply have a json file in say your user/data folder and use the onTwigPageVariables hook via your theme class or a simple plugin, to load that data (or load + cache) and store as a Twig variable for use by any twig logic in a page or template.
@rhukster: here's what you said in action.
{
public static function getSubscribedEvents() {
return [
'onTwigPageVariables' => ['onTwigPageVariables', 0],
];
}
public function onTwigPageVariables($event) {
$json = $event['page']->header()->json;
foreach ($json as $value) {
$fileName = str_replace(' ', '-', strtolower($value));
$data = file_get_contents('/user/data/' . $fileName . '.json');
$this->grav['twig']->twig_vars[${value}] = json_decode($data);
}
}
}
This allows you to grab multiple JSON files in the same Grav page. The twig variable is defined by the value in frontmatter which also calls the name of the file. So for example...
title: my page
json:
- jsonfile
- anotherfile
Frontmatter
{% for person in jsonfile %}
{{person.name}}
{{person.emailAddress}}
{% endfor %}
{% for person in anotherfile %}
{{person.name}}
{{person.emailAddress}}
{% endfor %}
Twig template
Man, this is exciting. Such powerful data processing!
Most helpful comment
@rhukster: here's what you said in action.
This allows you to grab multiple JSON files in the same Grav page. The twig variable is defined by the value in frontmatter which also calls the name of the file. So for example...
Frontmatter
Twig template
Man, this is exciting. Such powerful data processing!