"translating" a grid object to HTML structure (using VueJS)

Hey folks!

First off: This is my first post in this community, so please don’t kill me if I’m doing someting wrong but please feel free to tell me!

So - I’ve discovered Cockpit about a week ago and I’m absolutely in love with it because it enables me to hand craft websites while still allowing moderators and editors to edit the contents without having to touch code and possibly breaking my repo. Nice!

I’m currently in the process of building a VueJS frontend boilerplate for Cockpit, which I might even make public once I’m happy with the result, and all is working great so far.
But now I’m at a point where I’m creating Vue Components which represent the Cockpit Layout components, like headings, images and so on.
My problem is, that I can’t find a good way to “translate” the grid Object to HTML in a recursive way.
Sure, when I’d only take care of one layer, everything would be easy. But because you can nest grids inside grids, which is a common thing to do, I need to find a recursive solution.

I’m pretty sure the solution is actually quite simple, but my brain really hurts atm and I just can’t find a good way.

Any help would be appreciated! Let me know if I forgot to describe some aspects in greater detail.

Best regards from Germany :v:

I was able to solve it myself by discovering Vue’s recursive components.
What I’m doing now is, that I’m in fact just taking care of the first layer of the layout JSON. If the grid appears to have another grid nested into it, I just place the Vue grid component inside of itself.
Here’s some code. Let me know in case anyone of you needs help with this in the future.

Root Component (not in fact the root of my page, but root compared to the grid component)

// Import Cockpit partials (CMS objects for the layout field type)
import {cockpit_headings} from "../cockpit-partials/heading.js";
import {cockpit_images} from "../cockpit-partials/image.js";
import {cockpit_grid} from "../cockpit-partials/grid.js";

const pagecontents = {
    methods: {
        // Get data from the root component. Function gets triggered by root.
        fetchData: function() {
            this.data = this.$root.pageData.pagecontent;
        }
    },
    mounted: function () {
        let vue = this;
    },
    components: {
        c_heading: cockpit_headings,
        c_image: cockpit_images,
        c_grid: cockpit_grid
    },
    template:
        `
        <section class="cockpit-container">
            <div v-for="content in data" :data-cockpit-component="content.component">
            
                <c_heading v-if="content.component === 'heading'" v-bind:data="content"></c_heading>
                <c_image v-if="content.component === 'image'" v-bind:data="content"></c_image>      
                <c_grid v-if="content.component === 'grid'" v-bind:data="content"></c_grid>
                
            </div>
        </section>
        `
}

// Export the component
export {pagecontents}

Grid Component

import {cockpit_images} from "./image.js";
import {cockpit_headings} from "./heading.js";

const cockpit_grid = {
    name: "c_grid",
    props: {
        data: Object
    },
    components: {
        c_image: cockpit_images,
        c_heading: cockpit_headings
    },
    template:
        `
        <div class="row">
            <div v-for="col in data.columns" class="col">
                <div v-for="obj in col.children">
                    <c_image v-if="obj.component === 'image'" v-bind:data="obj"></c_image>
                    <c_heading v-if="obj.component === 'heading'" v-bind:data="obj"></c_heading>
                    <c_grid v-if="obj.component === 'grid'" v-bind:data="obj"></c_grid>
                </div>
            </div>
        </div>
        `
}
export {cockpit_grid}

Sounds interesting. Looking forward to your final version.

I’m working with VueJs myself, though not “VanillaVue” but rather as Nuxt projects, to build custom frontends with Cockpit as the headless CMS.

I’m curious what I can learn from your solution and how I might apply it to my Nuxt boilerplate.

Welcome to the Cockpit community.

@abernh I’ll come back to you once it’s done :slight_smile:
But pls don’t excpect too much. I’d describe myself as an amateur, but definitely not as a Pro :smiley:

Thanks for your kind words