Reputation: 400
I want to pass a piece of HTML to a table-data-element using VueJS. The following demonstrates my scenario:
<template>
<div>
<div v-if="someObject.properties" style="margin-top: 20px;" class="table-responsive-md">
<table class="table table-striped">
<thead>
<tr>
<th style="text-align: left" scope="col">Some icons</th>
</tr>
</thead>
<tbody v-for="(property, index) in someObject.properties" :key="index">
<tr>
<td style="text-align: center" v-html="getIconWhenSomeRequirementIsMet(property)"/>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script lang="ts">
...
getIconWhenSomeRequirementIsMet (property: any): string {
if (property.type === 'animal') return '<b-icon-check class="h3 mb-0" style="color:green;"/>'
if (property.type === 'human') return '<b-icon-check class="h3 mb-0" style="color:yellow;"/>'
return '<b-icon-x class="h3 mb-0" style="color:red;"/>'
}
</script>
The code above is a minimal example of my Vue single file component. However, this way, I get empty fields in my table instead of the actual icons. Isn't there a simple and clean approach to achieve this?
Upvotes: 0
Views: 2011
Reputation: 10324
The reason it doesn't work is because you can't use v-html
to render custom components.
Instead, here's two different ways you can do this.
The first is to pre-define your b-icon-*
and use v-if
, v-else-if
and v-else
to match which icon to show.
The second is to dynamically bind properties using v-bind
, this way you can use a method to do it, like you are now, but instead return the properties based on the type.
new Vue({
el: "#app",
data() {
return {
items: [
{ type: "animal" },
{ type: "human" },
{ type: "alien" },
],
fields: ['Type', 'Icon 1', 'Icon 2']
}
},
methods: {
getIconWhenSomeRequirementIsMet (type) {
/* Default properties */
const properties = {
icon: 'x',
style: 'color: red',
class: 'h3 mb-0'
};
if (type === 'animal') {
properties.icon = 'check';
properties.style = 'color: green;';
}
else if (type === 'human') {
properties.icon = 'check';
properties.style = 'color: yellow;';
}
return properties;
}
}
})
<link href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="//unpkg.com/[email protected]/dist/bootstrap-vue.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>
<script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue-icons.min.js"></script>
<div id="app">
<div class="table-responsive-md">
<table class="table table-striped">
<thead>
<tr>
<th v-for="field in fields" >{{ field }}</th>
</tr>
</thead>
<tbody>
<tr v-for="{ type } in items">
<td>
{{ type }}
</td>
<td>
<b-icon-check v-if="type === 'animal'" variant="success" class="h3 mb-0">
</b-icon-check>
<b-icon-check v-else-if="type === 'human'" variant="warning" class="h3 mb-0">
</b-icon-check>
<b-icon-x v-else variant="danger" class="h3 mb-0">
</b-icon-x>
</td>
<td>
<b-icon v-bind="getIconWhenSomeRequirementIsMet(type)"></b-icon>
</td>
</tr>
</tbody>
</table>
</div>
</div>
Upvotes: 2