DEV Community

Cover image for Generating dynamic layouts in Vue using recursive components
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)