'Is there a way to have a vue component whose template only contains the text of a property?
Is there a way to have a vue component which has a template area that only contains plain text? The problem I face with the current solution (using a div to wrap it around the text) is that I recursively concatenate these components with other text fragments in one line which often leads to jumps to the next row of the parent container because there is not enough space left on the right side of the text fragment that came before the current one. Consequently, text paragraphs which should look like this:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer molestie sit amet mauris sed sollicitudin. Curabitur non quam at nibh venenatis facilisis. Integer vitae augue vel quam condimentum ultricies. Mauris consequat elit vitae sollicitudin auctor. Donec volutpat velit nulla, vitae fermentum erat aliquet non. Mauris congue nibh eget justo sodales luctus.
Resultingly look like follows:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer molestie sit amet mauris sed sollicitudin.
Curabitur non quam at nibh venenatis facilisis. Integer vitae augue vel quam condimentum ultricies.
Mauris consequat elit vitae sollicitudin auctor. Donec volutpat velit nulla, vitae fermentum erat aliquet non.
Mauris congue nibh eget justo sodales luctus.
Under consideration that there are 5 text fragments in the above example, respectively.
This is how the said component is implemented with comments inside the template tags to concretize my issues:
<template>
<div>{{element.text}}</div> <!-- This is how I can do it to this point-->
{{element.text}} <!-- This is what I would like to do-->
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'
import TextElement from '@/models/elements/Text'
@Component
export default class TextWrapper extends Vue {
@Prop() element!: TextElement
}
</script>
<style scoped>
</style>
Solution 1:[1]
I solved the issue using a workaround for my initial intend by passing a css style property to the template of the parent vue-component:
<template>
<div>
<span v-for="(line, index) in paragraph.lines" :key="index">
<p v-if="line.length">
<span v-for="(lineFragment, index) in line" :key="index">
<component class="inline-component" :element="lineFragment" :is="lineFragment.type"/>
</span>
</p>
</span>
</div>
</template>
<script lang="ts">
import { Component, Prop } from 'vue-property-decorator'
import ElementHook from '@/views/ElementHook.vue'
@Component
export default class ParagraphWrapper extends ElementHook {
@Prop() element!: ParagraphElement
}
</script>
<style scoped>
.inline-component {
display: inline;
}
</style>
The ElementHook component serves as a basic abstract class which imports all the sub components which can be displayed via `:is="lineFragment.type" (e.g. 'text' for TextWrapper component).
If one wants to ensure the paragraphs are stilled wrapped around the borders of the parental container object, you want to consider adding white-space: pre-wrap;
to the css-class defined in the bottom part of the SFC.
Solution 2:[2]
Simple answer is no, render functions/templates require a root element. Instead of using a <div>
you can use an inline element such as a <span>
or style the div with the css property display: inline
to work around this issue.
Solution 3:[3]
Vue component templates should have root element that exists in DOM. Commonly div
or span
wrapper elements are used. This is rarely a a problem because root element can be styled to fit the layout.
There's vue-fragment plugin that provides the functionality of React.Fragment
in Vue. It basically unwraps root element on mount. Since it's a hack, it may not work in all situations as expected.
Render function can be used to render text nodes with _v
internal method. That it uses undocumented API suggests that it's a hack as well.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | nymvno |
Solution 2 | |
Solution 3 | Estus Flask |