DEV Community

Waruna
Waruna

Posted 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

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

Top comments (0)