Reputation: 1237
I'm writing a Vue.js app using BootstrapVue. I'm dynamically generating a form based on a simple "field" data structure (see code and screenshot below). The label for each <b-form-group>
comes from a label
attribute in my field object. It worked fine until I needed a subscript in the label. I'm using the <sub>
HTML tag, but v-bind
-ing the label treats the HTML as plain text. See the first column of inputs:
Next I tried using <b-form-group>
's label
slot instead, using mustache templates. As documented, this also interprets the value as plain text, so I get the same result -- see the second column.
Finally, I was able to achieve the result I wanted using v-html
in a span inside the label slot. This works (see the third column), but it seems a bit convoluted, and it's not making the linter happy (yes, I can always turn it off).
Is there a better way to achieve this? I'm relatively new to Vue.js.
(Note that I've simplified the example for brevity, omitting id
's, etc.)
<template>
<div class="m-4">
<b-container>
<b-form-row class="round-border">
<b-col
cols="4"
>
<b-form class="mr-4">
<b-form-group
v-for="(field, index) in fields"
:key="index"
:label="field.label"
>
<b-form-input
v-model.number="form[field.model]"
v-bind="field.atts"
/>
</b-form-group>
</b-form>
</b-col>
<b-col
cols="4"
>
<b-form class="mr-4">
<b-form-group
v-for="(field, index) in fields"
:key="index"
>
<label>{{ field.label }}</label>
<b-form-input
v-model.number="form[field.model]"
v-bind="field.atts"
/>
</b-form-group>
</b-form>
</b-col>
<b-col
cols="4"
>
<b-form class="mr-4">
<b-form-group
v-for="(field, index) in fields"
:key="index"
>
<label><span v-html="field.label" /></label>
<b-form-input
v-model.number="form[field.model]"
v-bind="field.atts"
/>
</b-form-group>
</b-form>
</b-col>
</b-form-row>
</b-container>
</div>
</template>
<script>
export default {
components: {},
data () {
return {
form: {
Length: 1,
Width: 4,
Height: 9
},
fields: [
{ label: 'Label<sub>1</sub>', model: 'Length', atts: { type: 'number', step: 1 } },
{ label: 'Label<sub>2</sub>', model: 'Width', atts: { type: 'number', step: 1 } },
{ label: 'Label<sub>3</sub>', model: 'Height', atts: { type: 'number', step: 1 } }
]
};
}
};
</script>
Upvotes: 1
Views: 649
Reputation: 5855
As @Ian Cho says, if the content of field.label
property is html as string, the only way to solve it in vue.js is using v-html
.
If you are able to change the field item structure to something like {label: 'Label', sub: 1, ...}
, you can use label slot as following:
<b-form-group v-for="(f, i) in fields">
<template slot="label">{{f.label}} <sub>{{f.sub}}</sub></template>
<!-- rest of your code -->
</b-form-group>
DEMO: https://jsfiddle.net/4xmr35p0/
Upvotes: 2
Reputation: 107
If you have to use HTML tags as parameter, v-html
is the only way.
If there's another way, please anyone let me know. ;)
Upvotes: 1