vue.jsvuejs2element-ui

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


How to return html formatted cell value?

I want to get custom formatted value (with html or other components) with <el-table-column> formatter.

<el-table :data="data">
  <el-table-column v-for="(column, index) in columns" 
                   :key="index" :label="column.label" 
                   :formatter="column.formatter">
  </el-table-column>
</el-table>
data() {
  return {
    columns: [
      {
        label: 'Created at',
        formatter: (row, col, value, index) => {
          return `<span class="date">${value}</span>`
        }
      },
      // edit:
      {
        label: 'Address',
        formatter: (row, col, value, index) => {
          return `<mini-map :data="${row}"></mini-map>`
        }
      }
      // other dynamic columns...
    ]
  }
}

But cell content is displayed as escaped html string. Is there any possibility to force html?

EPIC EDIT: I added an answer with a solution.


Solution

  • 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:

    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.