🔮 Dynamic Component Templates with Vue.js

Components do not always have the same structure. Sometimes there are many different states to manage. It can be helpful to do this asynchronously.

Philipp Kühn
Jun 26, 2018 · 3 min read

🤔 The Use Case

The most common previews for links — open graph data, images & videos
<template>
    <div class="comment">
        // comment text    
        <p>...</p>
    
        // open graph image
        <link-open-graph v-if="link.type === 'open-graph'" />        // regular image
        <link-image v-else-if="link.type === 'image'" />        // video embed
        <link-video v-else-if="link.type === 'video'" />
        ...
    </div>
</template>

🤯 Dynamic Component Templates

<template>
    <div class="comment">
        // comment text    
        <p>...</p>
    
        // type can be 'open-graph', 'image', 'video'...
        <dynamic-link :data="someData" :type="type" />
    </div>
</template>
folder structure for dynamic component templates
<template>
    <component :is="component" :data="data" v-if="component" />
</template><script>
export default {
    name: 'dynamic-link',
    props: ['data', 'type'],
    data() {
        return {
            component: null,
        }
    },
    computed: {
        loader() {
            if (!this.type) {
                return null
            }
            return () => import(`templates/${this.type}`)
        },
    },
    mounted() {
        this.loader()
            .then(() => {
                this.component = () => this.loader()
            })
            .catch(() => {
                this.component = () => import('templates/default')
            })
    },
}
</script>
<template>
    <component :is="someComponent"></component>
</template><script>
import someComponent from './someComponent'export default {
    components: {
        someComponent,
    },
}
</script>
computed: {
    loader() {
        if (!this.type) {
           return null
        }
        return () => import(`templates/${this.type}`)
    },
},
mounted() {
    this.loader()
        .then(() => {
           this.component = () => this.loader()
        })
        .catch(() => {
           this.component = () => import('templates/default')
        })
},

💡 Conclusion

Scrumpy

Agile Planning, Made Simple

Philipp Kühn

Written by

Designer and frontend developer, Co-Founder of @heyscrumpy

Scrumpy

Scrumpy

Agile Planning, Made Simple