vue.js - Dynamically inject Vue 2 component from shortcode -
i have form in admin area users can input text shortcodes in them:
heat oven @ [temp c=200]
what want temp
shortcode parsed , transformed vue 2 component when shown in front-end.
here's simplified temperature.vue
component:
<template> <span class="temperature"> {{ celsius }}°c </span> </template> <script> import { mapgetters, mapactions } 'vuex' export default { props: ['celsius'], name: 'temperature' } </script>
and here's simplified instructions.vue
component parse , render text shortcodes:
<template> <div v-html="parseshortcodes(text)"></div> </template> <script> import shortcodeparser 'meta-shortcodes' import temperature 'temperature.vue' export default { data: () => { return { text: 'heat oven @ [temp c=200]', parser: shortcodeparser() } }, components: [ temperature ], methods: { parseshortcodes(text) { return this.parser.parse(text) } }, created() { this.parser.add('temp', function(options) { return '<temperature :celsius="'+options.c+'"></temperature>' }) } } </script>
the parsing works fine, , substitution printed in front-end. <temperature>
tag rendered literally , not vue component, expected.
heat oven @ <temperature :celsius="200"></temperature>
what can't seem wrap head around step should take transform temperature
component have defined. possible? there more orthodox ways of doing missing?
there security concern of using v-html
render text. not want there, i'm guessing it's more far-fetched expect temperature
component appear escaped string. can sanitise prior insertion on database, i'd still avoid v-html
if @ possible.
in order make example work you'll need use render function of instructions component. in render function can create new vue component, lets 'intruction', you'll pass string resulted shortcode parse use template. in component declaration you'll append temperature component child , render prop you've passed. , that's it. example follows:
instructions.vue
<script> import shortcodeparser 'meta-shortcodes' import temperature 'temperature.vue' export default { data: () => { return { text: 'heat oven @ [temp c=200]', parser: shortcodeparser() } }, methods: { parseshortcodes(text) { return this.parser.parse(text) } }, render (createelement) { const template = this.parseshortcodes(this.text) //returns <div class="intruction">'heat oven @ <temperature :celsius="200"></temperature>'</div> var component = vue.component('instruction', { template: template, components: { 'temperature': temperature } }) return createelement( 'div', { class: { instructions: true } }, [ createelement(component) ] ) } } </script>
Comments
Post a Comment