Reputation: 2220
I'm generating a table based on a 2D array in Vue2. I can get the table to display fine with all the values in the right spots but I'm having trouble with the formatting. The template looks something like this:
<table>
<thead>
<tr>
<th>Title</th>
<th>Column 1</th>
<th>Column 2</th>
</tr>
</thead>
<tbody>
<tr v-for="row in data">
<td>{{row[0]}}</td>
<td>{{row[3]+row[1]+row[4]}}</td>
<td>{{row[3]+row[2]+row[4]}}</td>
</tr>
</tbody>
</table>
And the data looks something like this:
var data = [
['revenue', 123.4, 153.48, '$'],
['cost', 93.26, 109.48, '$'],
['profit', 30.14, 44, '$'],
['margin', 24.425, 28.668, '', '%']
];
This works... ish. I can have whatever rows I want and I can specify the units—prefixed or suffixed—but it isn't perfect. The biggest issue is that currency has different numbers of decimal places. I could store those values as strings, but some of them are reused in calculations which means I would have to parse them.
It was at this point that I came across filters. Since this project that I've inherited already has a bunch built in, it seems they will do exactly what I want. I can just change it to {{row[1] | currency}}
and it spits it out all nicely formatted. The only problem is that I have mixed data types. In the example, revenue
, cost
, and profit
are all currency values, but margin
is a percentage.
Ideally I would like to specify the filter in the 4th index of each array:
var data = [
['revenue', 123.4, 153.48, 'currency'],
['cost', 93.26, 109.48, 'currency'],
['profit', 30.14, 44, 'currency'],
['margin', 24.425, 28.668, 'percent']
];
and then use something like this to spit out the values:
<td>{{row[1] | row[3]}}</td>
<td>{{row[2] | row[3]}}</td>
However, this doesn't seem to work. I also tried filters[row[3]]
and a bunch of other variations but it seems like the syntax for that doesn't exist. I can of course write my own functions for formatting and then use something like this.formatters[row[3]](row[1])
, but it doesn't make a lot of sense to re-implement something that already exists. If there's a way to access the filters' underlying functions without making it too messy I could do that but it doesn't seem ideal.
The ideal solution would be a way to use the existing filters to format the output all within the table. Calling the functions on the values directly would also be okay. Failing that, I could pre-format the values and store them as strings in a separate object, using the existing functions, but that isn't ideal.
Upvotes: 4
Views: 2589
Reputation: 55664
The documentation on Vue filters is lacking, but you apparently cannot access filters dynamically like you are wanting to do.
Your best option is to keep your formatting functions in an object like you suggest.
You could make it a little cleaner by adding a catchall filter to your component and pass the type as a parameter:
filters: {
format(value, type) {
return this.formatters[type](value);
}
}
Then in your template:
<td>{{row[2] | format(row[3]) }}</td>
Upvotes: 1
Reputation: 82489
This will allow you to keep your data format and use existing filters.
new Vue({
el:"#app",
data:{
data: [
['revenue', 123.4, 153.48, "currency"],
['cost', 93.26, 109.48, "currency"],
['profit', 30.14, 44, "currency"],
['margin', 24.425, 28.668, "percent"]
]
},
methods:{
format(value, filter){
return Vue.filter(filter)(value)
}
}
})
Template
<tr v-for="row in data">
<td>{{row[0]}}</td>
<td>{{format(row[1], row[3])}}</td>
<td>{{format(row[1], row[3])}}</td>
</tr>
Upvotes: 5