background

ElementUI is an excellent component library, but the way its Table component is used always gives me a bit of a problem. Let’s take a look at the official documentation for an example:

<el-table
  :data="tableData"
  style="width: 100%">
  <el-table-column
    prop="date"
    label="Date"
    width="180">
  </el-table-column>
  <el-table-column
    prop="name"
    label="Name"
    width="180">
  </el-table-column>
  <el-table-column
    prop="address"
    label="Address">
  </el-table-column>
</el-table>
Copy the code

Developers need to register the columns they want to display in an El-Table component with an El-table-column. Imagine if the table had many columns and you had to write a large number of El-table-columns in the template, which would increase maintenance costs. The tables of other component libraries in the community can render the desired columns using an array of columns. Let’s take a look at the official example of iView:

<template>
    <Table :columns="columns" :data="data"></Table>
</template>
<script>
  export default {
    data () {
      return {
        columns: [{title: 'Name'.key: 'name'
          },
          {
            title: 'Age'.key: 'age'
          },
          {
            title: 'Address'.key: 'address'}].// ...}}}</script>
Copy the code

In addition, because there are a large number of column phenotype pages in our management background project, the structure of such pages are mostly the same, so I want to go further on the basis of Table, so the TableView component came into being.

TableView

TableView is a page container with a Table as the main content, such as managing the various lists in the background project. This kind of page generally contains search, table, footer, toolbar and table customization several parts, page features are obvious, high reusable. TableView allows you to render all columns in a table by passing in an array of columns. Each column can also be customized via the Render function or slots. It also has built-in paging logic and allows the user to customize which columns to display, but the search form part has to be done by the user and slots into the TableView.

The TableView structure is shown as follows:

Internals provides built-in functionality for components, including list rendering in the Table section, pagination in the Footer section, and list customization in the Customer section (customizing which columns to display).

Slots currently contains:

  • filter

    Page filter, embedded search form

  • tabBar

    Some pages need TAB switching at the top, such as the pending review list under the order management module, which is subdivided into “pending review”, “preliminary review returned” and other states.

  • toolBar

    Toolbar part, you can embed some buttons in this, such as: export, new.

use

Basic usage

The red part in the figure is the TableView. The user can render the table by passing in an array of columns. The code is as follows:

<template>
  <table-view
    :columns="columns"
    get-list-method="getDataList"
  >
    <template #filter="{ search }">
      <order-filter
        @search="search($event)"
        @reset="search($event)"
      />
    </template>

    <template #toolBar>
      <el-button
        type="primary"
        size="small"
      >export</el-button>
    </template>
  </table-view>
</template>

<script>
export default {
  // ...
  data() {
    return {
      columns: [{label: 'Name'.prop: 'name'}, {label: 'Age'.prop: 'age'
        },
        {
          label: 'Address'.prop: 'address'}}; },methods: {
    async getDataList(params) {
      const res = await Api.getList(params)
      return {
        listData: res.list,
        total: res.total,
        page: res.page
      }
    }
  }
};
</script>
Copy the code

The complete attributes of the column object that describe each column are shown below, giving you the flexibility to control the presentation of each column

{
  // required
  label: 'name'.// required
  prop: 'name'.// ElTableColumn attribute
  elProps: {
    fixed: true,},// Whether to display
  // Component prop 'useColumnCustomer' takes effect when it is true
  // show columns with false are hidden
  show: true.// You can customize the contents of each column by using the render function
  // row: row data
  // col: column data
  // rowIdx: row index (starting from 0)
  // colIdx: column index (starting from 0)
  render(h, { row, col, rowIdx, colIdx }) {
    return h(
      'div', 
      { / *... * / },
      `${row.name}`)}}Copy the code

How do I customize columns?

TableView supports column customization through render function and slot

Note: Render takes precedence over slots

1. The render function

Set up a render function for the columns you want to customize, which you can use to render the desired content. If your custom content is complex, you can wrap a component and pass it to the render function as if it were an action column.

import OperationWidget from './OperationWidget.vue'

export default {
  // ...
  data() {
    return {
      columns: [{label: 'name'.name: 'prop'.render(h, { row, col, rowIdx, colIdx }) {
            return h(
              'div', 
              { / *... * / },
              `${row.name}`)}}, {label: 'operation'.prop: 'operation'.render(h, { row }) {
            return h(OperationWidget, {
              props: {
                orderInfo: row } }) } } ]; }}}Copy the code

2. The slot

TableView allows you to customize columns through named slots, slots named column prop

<template>
  <table-view
    :columns="columns"
    :get-list-method="getListMethod">
    <! -- 'name' slot will customize column prop as 'name' -->
    <template #name="{ row }">
      <! -- slot what you want -->
      <div>{{ row.name }}</div>
    </template>
  </table-view>
</template>
Copy the code

How do I request data?

The TableView requires the user to call the interface in getListMethod and backfill the data. GetListMethod is written in two ways:

  1. An asynchronous write

The first is to write a function that returns a Promise, which takes the data returned by the resolve interface, like this:

async getDataList(params) {
  const res = await Api.getList(params)
  return {
    listData: res.list, // Table data
    total: res.total,   / / the total number of
    page: res.page      // The current number of pages}}Copy the code
  1. The callback method

The TableView calls getListMethod with two parameters. The first is the request parameter, and the second is a callback function that sets the data.

getDataList(params, callback) {
  Api
	.getList(params)
	.then(res= > {
		callback({
	    listData: res.list, // Table data
	    total: res.total,   / / the total number of
	    page: res.page      // The current number of pages}}))Copy the code

How to search?

TableView requires the user to sort out the search criteria by himself, and then manually call the internal method search, as shown in the figure:

There are two ways to call search:

1. Through the scope slot

<table-view
  :columns="columns"
  get-list-method="getDataList"
>
  <template #filter="{ search }">
    <order-filter
      @search="search($event)"
      @reset="search($event)"
    />
  </template>
</table-view>
Copy the code

2. Through the ref

<template>
	<table-view
	  ref="tableView"
	  :columns="columns"
	  get-list-method="getDataList"
	>
	  <template #filter>
	    <order-filter
	      @search="search($event)"
	      @reset="search($event)"
	    />
	  </template>
	</table-view>
</template>

<script>
export default {
  // ...
  methods: {
    search(params) {
      this.$refs.tableView.search(params)
    }
  }
}
</script>
Copy the code

Use the built-in custom list feature

TableView built-in custom column components, support the user to select the column to display, hide the excess column.

To use this feature, set useColumnCustomer to true and pass the columnCustomMethod method to the component. You need to update columns with the columnCustomMethod, setting show to true for custom columns and show to false for other columns.

<table-view
  :columns="columns"
  use-column-customer
  :column-custom-method="columnCustomMethod"
  get-list-method="getDataList"
>
  <! -... -->
</table-view>
Copy the code
export default {
  // ...
  methods: {
    /** * Handle list custom */
    columnCustomMethod(columnProps) {
      this.columns = this.columns.map(col= > ({
        ...col,
        show: columnProps.includes(col.prop)
      }))
      // ...}}}Copy the code

You can also go one step further and store user-defined data in the columnCustomMethod and set show to true for the columns corresponding to the saved data the next time you render the table.

The source code

So much for TableView. If you’re interested, head over to GitHub for the source code and full documentation. For advice please ask star 🌟. In addition, I wrapped the Table as a separate component, so if you only want to use the Table part, look directly at the SRC/table.vue file

GitHub – JackLiR8/table-view