Vue element-ui <el-table-column> formatter – how to display html? Vue element-ui <el-table-column> formatter – how to display html? vue.js vue.js

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')