DEV Community

Cover image for Generating dynamic layouts in Vue using recursive components
Waruna
Waruna

Posted on • Edited on

Generating dynamic layouts in Vue using recursive components

Inspiration for this article comes from a recent implementation I did to build dynamic layouts on Vue based front end.

Let's assume your API endpoint returns a YAML layout like below.

---
row:
  - col: 12
    row:
      - col: 12
        component_id: 1
  - col: 12
    row:
      - col: 6
        component_id: 2
      - col: 6
        row:
          - col: 12
            component_id: 3
          - col: 12
            component_id: 4
Enter fullscreen mode Exit fullscreen mode

We would expect a layout like the below from this YAML expression.

Image description

So, it make this easy to work with we will parse this YAML structure and generate JSON object. I used yaml package.

npm install yaml

Enter fullscreen mode Exit fullscreen mode

Then, we could import it and run the parser.

import YAML from 'yaml'
const jsonObject = YAML.parse(yaml_struct)
Enter fullscreen mode Exit fullscreen mode

To make this work, we need to create a recursive Vue template and a component that can call itself recursively when encountering nested rows. This way, the structure will dynamically handle deeply nested layouts like the one I provided.

<template>
    <v-row>
        <template v-for="col in row">
            <v-col :cols="col.col">
                <template v-if="col.component_id">
                    <ComponentWantToRender :col="col"></ComponentWantToRender>
                </template>

                <template v-if="col.row">
                    <RecursiveRow :row="col.row"></RecursiveRow>
                </template>
            </v-col>
        </template>
    </v-row>
</template>

<script setup>
import { defineProps } from 'vue';
import RecursiveRow from './RecursiveRow.vue';
defineProps({
    row: Array,
});
</script>
Enter fullscreen mode Exit fullscreen mode

Now, we can use this RecursiveRow component inside your parent component to handle the top-level layout.

<template>
  <RecursiveRow :row="jsonObject"></RecursiveRow>
</template>

<script setup>
import RecursiveRow from './RecursiveRow.vue';

defineProps({
  jsonObject: Array,
});
</script>
Enter fullscreen mode Exit fullscreen mode

You can find full working version of this here: Github Link

That's it. If you have any questions, please leave a comment below.

Top comments (0)