Newbie problem: Can not get collection json output

Hello there.
Very new to Grav but not new to web development.

What I want:
Make a new custom post type (flex object) and then pull all the posts from json to display in another application.

What I did:
Create yaml in blueprint, activate it in the flex-objects plugin, create a few posts in backend. This all works fine. I created a new page (flex-objects with my type as collection) and I can list all the posts in the page as html nicely.

What doesn’t work:
Next to the collection/default.html.twig, I also created a default.json.twig that’s supposed to give me the json of all the objects. But it doesn’t. If I call the /page.json, it will still give me the html output.
I’m stuck here how I can get the json output. I’m pretty sure it’s very simple and I’m just missing one crucial step.

Thank you very much in advance!

Kind regards

What’s in your default.json.twig?

So far, nothing more than “this is default.json.twig” to see if the file gets actually parsed. No bueno?

I assume you did everything by this example and you have json listed in system.yaml (default is pages: types: [html,htm,xml,txt,json,rss,atom]) and you also have templates named as they should be depending on your structure.

What if you try to return a valid JSON instead of random test string?

I’ve been following this example: GitHub - trilbymedia/grav-plugin-flex-objects: Powerful and supremely flexible object support for Grav

I put the templates into user/themes/quark/templates/flex-objects/layouts/testjson/collection and /objects

I have referred to them in the testjson.yaml file.

What do I have to put into the .json file? Is it enough to put {{ object.name | json_encode }} or do I need to give it any further structure?

OK, I think i know where you should start looking at. The place where you have {% include 'flex-objects/page.html.twig' %}. This most likely is called from another ...html.twig template, which your page resolves to. page.html.twig, which is in FO (Flex Objects) plugin then calls other ...html.twig templates to render objects output.

I believe you’ll have to add your main template template.json.twig where you call also newly added {% include 'flex-objects/page.json.twig' %} which should probably be a copy of html version, but all calls to html templates should be replaced to json (also contents)

Does that make sense? I could try to explain in more detail after work :slight_smile:
I could try make a plugin, which would add all of these templates

Thank you very much. However, I can’t find any place where page.html.twig gets called.

I have found a default.html.twig in quark/templates, which has
{% extends ‘partials/base.html.twig’ %}

{% block content %}
{{ page.content|raw }}
{% endblock %}

But no luck searching for page.html.twig… I can’t see through all of this to be honest. It sounds so easy in the documentation, but whatever I try, it just ignores me :confused:

Which template gets resolved (full path from /user would be good) when you visit your page without .json extension where you see your objects listed? I understand objects are listed on page, right?

Well, I’ve been toying around with this and in user/templates I have found default.html.twig to be working. I tried
{% block content %}
{
‘content’ : {{ page.content|json_encode }}
}

{% endblock %}

And it gives me something that I could build up upon.

BUT! This template does not work for my collection. It still gives me the normal html output and I don’t understand which the base template is that it gets its output from. So I don’t know which template gets listed.

How can I debug this thing? How can I have it tell me which template it uses? It’s like fishing in the dark…

Do you see your objects on the page if you navigate to it without a .json extension? If so, I would have to figure out how collections are rendered :thinking:

Could you also share the frontmatter of the resolved page default.md?

So far, I have:

  • The page for the collection is called test and the template seems to be /user/templates/flex-objects.html.twig.

Here, I can set
{{ page.content|json_encode|raw }}

and the page then doesn’t render in html, which is good.

But then, there is a dead end for me because, well, now it’s outputting two quotation marks without any further content. Neither from the collection, which then should just echo the existing content in plain html as the page.content is set to json_encode, no?

I think I’m totally lost now.

edit: yes, I can see my collection as html. And I have also managed to get the normal html-output as well as seeing a different output if I add .json to the url slug. But when I add the .json, I simply get an empty page with quotation marks, the content is missing. I’m not sure how to get there.

Now I’m lost too. You said on several occasions I think, that /user/templates/default.html.twig is rendered, but now you say it’s /user/templates/flex-objects.html.twig :slight_smile: Did you change something?

Anyway, now you need to create /user/templates/flex-objects.json.twig, which should be rendered when you navigate to .json URL

They both get rendered, default.html.twig renders the normal pages and flex-objects.html.twig seems to render the page that shall list the collection.

I have created the user/templates/flex-objects.json.twig and it refers to page.json.twig, which I have access to the page.content from.

Buuuuuuut, I still have no idea how to show the content of the collection inside of this page.

Could you paste the contents of /user/templates/flex-objects.html.twig?
And where did it come from? Did you copy it from FO plugin?

How both templates get rendered if both extend base template? I believe you’re missing something here. These templates can be rendered only on different pages, but not both on same page :confused:

Anyway, give me a few hours and I’ll try to make a plugin with all the JSON templates. Then you should get your JSON objects if you set page to use FO template

Yes, I copied it from flex-object plugin.

This is the content:
{% block content %}
{% block page_content %}
{{ page.content|json_encode|raw }}
{% endblock %}

{% block flex_content %}
    {% set options = page.header.flex %}
    {% set page_assets = page.header.assets %}
    {% set type = options.directory ?? page.header.directory ?? uri.param('directory') %}
    {% set id = options.id ?? uri.param('id') %}

    {% include 'flex-objects/page.json.twig' %}
{% endblock %}

{% endblock %}

I’d be VERY grateful (like, very, very, very, very, very, very!!!) for your plugin, much appreciated!

In the meantime, I’m digging out some more. THANK YOU!

OK, here it is :slight_smile:

Check the README how to use, install by using Manual method and tell me if that’s what you wanted :wink:

1 Like

Good morning!

Thank you very much, that brought me almost to the finish line…
But the output of the flex-items themselves are still in HMTL, which is now embedded in json.
How can I get “naked” json, for example:
“id”: “testitem1”
image: “testitem.jpg”
tags": “test, test2, test3”

I have already created a default.json.twig in /templates/flex/testjson/collection
but it looks like it’s pulling the default.html.twig and not the default.json.twig

I got it! My page.html.twig was in the way!

It’s perfect! THANK YOU SO MUCH!!

1 Like