I have the following vue instance which has a method to conditionally return some html markup. As you can see the markup is identical for each condition, only different styles are being applied.
Is there a more elegant way to achieve the same? Also should I be using a method or a computed property or a component to achieve this - If I should use a computed property how to I pass the value to evaluate ?
Any one know any other way?
<div v-for="item in items">
<div v-if="!_.isEmpty(item.files)">
<ul >
<li v-for="file in item.files">
<span v-html="fileIcon(file.fileExtension)"></span>
</li>
</ul>
</div>
</div>
var vm = new Vue({
el: '#root',
data: {
items: [
{
"id": 126,
"content": "blah...",
"files": [
{
"id": 8,
"filename": "test.doc",
"fileExtension": "doc"
}
]
},
{
"id": 127,
"content": "blah...",
"files": []
}
]
},
methods: {
fileIcon: function (extension) {
var str;
switch (extension)
{
case "jpg":
case "jpeg":
case "png":
case "gif":
str = "<i class='fa fa-file-image-o file-picture'></i>";
break;
case "pdf":
str = "<i class='fa fa-file-pdf-o file-pdf' ></i>";
break;
case "xls":
case "xlsx":
str = "<i class='fa fa-file-excel-o file-excel' ></i>";
break;
case "doc":
case "docx":
str = "<i class='fa fa-file-word-o file-word' ></i>";
break;
default:
str = "<i class='fa fa-file-file-o file-empty' ></i>";
break;
}
return str;
}
}
});
Please note I'm very new to Vue so some code snippet to guide would be appreciated.
I don't think you need/should use v-html for something like this.
You just need to set up a map to link type to class
define the object
let icons = {
jpg: ['fa-file-image-o', 'file-picture'],
jpeg: ['fa-file-image-o', 'file-picture'],
png: ['fa-file-image-o', 'file-picture'],
gif: ['fa-file-image-o', 'file-picture'],
pdf: ['fa-file-pdf-o', 'file-pdf'],
xls: ['fa-file-excel-o', 'file-excel'],
xlsx: ['fa-file-excel-o', 'file-excel'],
doc: ['fa-file-word-o', 'file-word'],
docx: ['fa-file-word-o', 'file-word']
}
create a method
fileIcon (type) {
return icons[type] || ['fa-file-file-o', 'file-empty']
}
then call it in the template <span :class="fileIcon(file.fileExtension)">
You can use methods to return classes, see this codepen:
https://codepen.io/huntleth/pen/POdGRL
See here for more info: https://v2.vuejs.org/v2/guide/class-and-style.html
Ideally, you would store the file types and their corresponding classes in data as well, this would reduce complexity of the method.
var vm = new Vue({
el: '#app',
data: {
items: [
{
"id": 126,
"content": "blah...",
"files": [
{
"id": 8,
"filename": "test.doc",
"fileExtension": "doc"
}
]
},
{
"id": 127,
"content": "blah...",
"files": []
}
]
},
methods: {
fileIcon: function (file) {
var ext = file.fileExtension;
var str;
switch (ext)
{
case "jpg":
case "jpeg":
case "png":
case "gif":
str = "fa fa-file-image-o file-picture";
break;
case "pdf":
str = "fa fa-file-pdf-o file-pdf";
break;
case "xls":
case "xlsx":
str = "fa fa-file-excel-o file-excel";
break;
case "doc":
case "docx":
str = "fa fa-file-word-o file-word";
break;
default:
str = "fa fa-file-file-o file-empty";
break;
}
return str;
}
}
});
<div id="app">
<div v-for="item in items">
<div v-if="!_.isEmpty(item.files)">
<ul >
<li v-for="file in item.files">
<i :class="fileIcon(file)">{{file.filename}}</i>
</li>
</ul>
</div>
</div>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With