I have a component like this:
Relation.vue
<template>
<div :is="dynamicRelation"></div>
</template>
<script>
import Entry from '@/components/Entry';
import weirdService from '@/services/weird.service';
export default {
name: 'Relation',
data() {
return {
entry1: { type: 'entity', value: 'foo', entity: {id: 4}},
entry2: { type: 'entity', value: 'bar', entity: {id: 5}},
innerText: '@1 wut @2',
}
},
computed: {
dynamicRelation() {
return {
template: `<div>${this.innerText
.replace('@1', weirdService.entryToHtml(this.entry1))
.replace('@2', weirdService.entryToHtml(this.entry2))}</div>`,
name: 'DynamicRelation',
components: { Entry }
};
}
}
}
</script>
wierd.service.js
export default {
entryToHtml(entry) {
[some logic]
return `<entry entry='${JSON.stringify(entry)}'></entry>`;
// unfortunately I cannot return JSX here: <entry entry={entry}></entry>;
// I get 'TypeError: h is not a function'
// unless there is a way to convert JSX to a pure html string on the fly
}
}
Entry.vue
<template>
<div>{{objEntry.name}}</div>
</template>
<script>
export default {
name: 'Entry',
props: {
entry: String // I need this to be Object
},
computed: {
objEntry() {
return JSON.parse(this.entry);
}
}
}
</script>
The innerText property decides how the components will be rendered and it can be changing all the time by having its @ slots in any position. In this example the result is:
<div>
<div>foo</div>
wut
<div>bar</div>
</div>
This works since Entry
component has as a property entry
that is of type String
but I have to JSON.stringify()
the entry object in weirdService
side and then in Entry
component I have to JSON.parse()
the string to get the real object back.
How can I make the above work so that I pass an object directly to a dynamic template so I avoid serialization and deserialization all the time.
btw for this to work runtimeCompiler needs to be enabled in vue.config.js:
module.exports = {
runtimeCompiler: true
}
I know I can use JSX to return components with objects in them but this is allowed only in render() function it seems and not custom ones like mine.
I was able to do what I wanted by using JSON.stringify still but pass the entry as object :entry
wierd.service.js
export default {
entryToHtml(entry) {
return `<entry :entry='${JSON.stringify(entry)}'></entry>`;
}
}
Entry.vue
<template>
<div>{{entry.name}}</div>
</template>
<script>
export default {
name: 'Entry',
props: {
entry: Object
}
}
</script>