Vue element-ui <el-table-column> formatter – how to display html?
Ok, after a few hours of brainstorming I found pretty nice solution. I'm putting it here for others - I hope this helps somebody.
Value displayed in custom column can be:
simple string (prop)
formatted string (safe, without any html or components, via original formatter)
customized value (html, component, also safe!)
In order to achieve this, I had to create custom formatter components, which I put in folder i.e. /TableFormatters/
For this purpose, there is simple functional component DatetimeFormatter that display date-time with icon.
TableFormatters/DatetimeFormatter.vue
<template functional> <span> <i class="icon-date"></i> {{ props.row[props.column] }} </span></template><script> export default { name: 'DatetimeFormatter', }</script>
Here come's columns configuration:
import DatetimeFormatter from './TableFormatters/DatetimeFormatter'// ...data() { return { data: [/*...*/], columns: [ name: { label: 'Name', }, state: { label: 'State', formatter: row => { return 'State: '+row.state__label } }, created_at: { label: 'Created at', formatter: DatetimeFormatter } ] }}
Now it's time to define <el-table>
:
<el-table :data="data"> <el-table-column v-for="(column, index) in columns" :key="index" :label="columns[column] ? columns[column].label : column" :prop="column" :formatter="typeof columns[column].formatter === 'function' ? columns[column].formatter : null"> <template #default="{row}" v-if="typeof columns[column].formatter !== 'function'"> <div v-if="columns[column].formatter" :is="columns[column].formatter" :row="row" :column="column"> </div> <template v-else> {{ row[column] }} </template> </template> </el-table-column></el-table>
This works like a charm. What's going on here with formatter?First we check if the formatter is set as a function
. If so, the native <el-table-column>
formatter takes the control, because <template #default={row}>
will not be created. Otherwise formatter component will be created (via :is
attribute). However, it there is no formatter, the plain value for a row will be shown.
If you want to render custom HTML for a <el-table-column>
, you will need to make use of the custom column template functionality, rather than the :formatter
prop. It's going to look something like this:
<el-table :data="data"> <el-table-column v-for="(column, index) in columns" :key="index" :label="column.label" > <template slot-scope="scope"> <span class="date">{{ scope.row.value }}</span> </template> </el-table-column></el-table>
In the general case, you can make use of the v-html
directive if you need to render unescaped HTML. There are some security implications involved, so make sure you understand those before reaching for v-html
.
Essentially, it boils down to this: never use v-html
to render content that was provided by the user.
Use template slot scope to add html formatted columns
<script src="//unpkg.com/vue/dist/vue.js"></script><script src="//unpkg.com/element-ui/lib/index.js"></script><div id="app"><template><el-table :data="tblData"> <el-table-column prop="title"></el-table-column> <el-table-column prop="text"> <template scope="scope"> <span style="color:red;">{{scope.row.text}}</span> </template> </el-table-column></el-table></template></div>var Main = { data() { return { tblData : [ {title: 'title1', text:'text1'}, {title: 'title2', text:'text2'}, {title: 'title3', text:'text3'}, ], } }, methods : { }}var Ctor = Vue.extend(Main)new Ctor().$mount('#app')