Table

Table is required to be used within Column.

Demos

Size & stylistic variants

Available variant for the ui prop: slim/alt/bordered.

ID
Name
Bid
Last updated
Operations
3154
Steve Rogers
¥1024.00
2013-11-17
3155
Thor Odinson
¥598.00
2014-02-14
3156
Tony Stark
¥820.00
2017-06-10
3157
Stephen Strange
¥736.00
2018-01-09
<template>
<article>
  <section>
    <veui-checkbox v-model="slim">
      Slim
    </veui-checkbox>
    <veui-checkbox v-model="alt">
      Alternative
    </veui-checkbox>
    <veui-checkbox v-model="bordered">
      Bordered
    </veui-checkbox>
  </section>
  <section>
    <veui-table
      :ui="ui"
      :data="data"
      key-field="id"
    >
      <veui-table-column
        field="id"
        title="ID"
      />
      <veui-table-column
        field="name"
        title="Name"
      />
      <veui-table-column
        field="bid"
        title="Bid"
        width="160"
        align="right"
      >
        <template slot-scope="{ bid }">
          {{ bid | currency }}
        </template>
      </veui-table-column>
      <veui-table-column
        field="updateDate"
        title="Last updated"
        align="center"
      >
        <template slot-scope="{ updateDate }"></template>
      </veui-table-column>
      <veui-table-column
        field="operation"
        title="Operations"
      >
        <template slot-scope="{ index }">
          <veui-button
            ui="link alert"
            @click="remove(index)"
          >
            Remove
          </veui-button>
        </template>
      </veui-table-column>
    </veui-table>
  </section>
</article>
</template>

<script>
import { Checkbox, Table, Column, Button } from 'veui'

export default {
  components: {
    'veui-table': Table,
    'veui-table-column': Column,
    'veui-checkbox': Checkbox,
    'veui-button': Button
  },
  filters: {
    currency (value) {
      return '¥' + value.toFixed(2)
    },
    date (value) {
      let [, ...parts] = value.match(/(\d{4})(\d{2})(\d{2})/) || []
      return parts.join('-')
    }
  },
  data () {
    return {
      slim: false,
      alt: false,
      bordered: false,
      data: [
        {
          id: '3154',
          name: 'Steve Rogers',
          bid: 1024,
          updateDate: '20131117'
        },
        {
          id: '3155',
          name: 'Thor Odinson',
          bid: 598,
          updateDate: '20140214'
        },
        {
          id: '3156',
          name: 'Tony Stark',
          bid: 820,
          updateDate: '20170610'
        },
        {
          id: '3157',
          name: 'Stephen Strange',
          bid: 736,
          updateDate: '20180109'
        }
      ]
    }
  },
  computed: {
    ui () {
      return [
        ...(this.slim ? ['slim'] : []),
        ...(this.bordered ? ['bordered'] : []),
        ...(this.alt ? ['alt'] : [])
      ].join(' ')
    }
  },
  methods: {
    remove (index) {
      this.data.splice(index, 1)
    }
  }
}
</script>

<style lang="less" scoped>
section {
  margin-bottom: 20px;
}

.veui-checkbox {
  margin-right: 20px;
}
</style>

Advanced

Supports specifying row keys, mode of selection, and sorting by values of specific column.

ID
Group
Name
Bid
Last updated
Opertaions
3154
1577
Steve Rogers
¥1024.00
2013-11-17
3155
Thor Odinson
¥598.00
2014-02-14
3156
1578
Tony Stark
¥820.00
2017-06-10
3157
Stephen Strange
¥736.00
2018-01-09

Selected: ["1577"]

<template>
<article>
  <section>
    <veui-button
      ui="primary"
      @click="append"
    >
      Add
    </veui-button>
  </section>
  <section>
    <veui-checkbox
      v-model="mode"
      true-value="multiple"
      false-value="single"
    >
      Multiple selection
    </veui-checkbox>
    <veui-checkbox v-model="showOps">
      Display “Operations”
    </veui-checkbox>
    <veui-checkbox v-model="selectSpanRow">
      Select by “Group” <small>(instead of “ID”)</small>
    </veui-checkbox>
  </section>
  <section>
    <veui-table
      ui="alt bordered"
      :data="data"
      :key-field="selectSpanRow ? 'group' : 'id'"
      selectable
      :select-mode="mode"
      :order-by="orderBy"
      :order="order"
      :selected.sync="selected"
      @sort="handleSort"
    >
      <veui-table-column
        field="id"
        title="ID"
        sortable
      >
        <template slot="head">
          <strong>ID</strong>
        </template>
        <template slot="foot">
          <strong>Total</strong>
        </template>
      </veui-table-column>
      <veui-table-column
        field="group"
        title="Group"
        :span="groupSpan"
      />
      <veui-table-column
        field="name"
        title="Name"
        width="160"
      />
      <veui-table-column
        field="bid"
        title="Bid"
        sortable
        width="160"
        align="right"
      >
        <template slot-scope="{ bid }"></template>
        <template slot="foot">
          <strong>{{ total | currency }}</strong>
        </template>
      </veui-table-column>
      <veui-table-column
        field="updateDate"
        title="Last updated"
        align="center"
      >
        <template slot-scope="{ id, updateDate }">
          <span :ref="`time-a-${id}`">{{ updateDate | date }}</span>
          <veui-tooltip :target="`time-a-${id}`">
            {{ updateDate | time }}
          </veui-tooltip>
        </template>
      </veui-table-column>
      <veui-table-column
        v-if="showOps"
        field="operation"
        title="Opertaions"
      >
        <template slot-scope="{ index }">
          <veui-button
            ui="link alert"
            @click="del(index)"
          >
            Remove
          </veui-button>
        </template>
      </veui-table-column>
    </veui-table>
    <p>Selected: {{ JSON.stringify(selected) }}</p>
  </section>
</article>
</template>

<script>
import { groupBy } from 'lodash'
import { Button, Checkbox, Table, Column, Tooltip } from 'veui'

export default {
  components: {
    'veui-button': Button,
    'veui-table': Table,
    'veui-table-column': Column,
    'veui-tooltip': Tooltip,
    'veui-checkbox': Checkbox
  },
  filters: {
    currency (value) {
      return '¥' + value.toFixed(2)
    },
    date (value) {
      let [, ...parts] = value.match(/(\d{4})(\d{2})(\d{2})/) || []
      return parts.join('-')
    },
    time (value) {
      let [, ...parts] = value.match(/(\d{4})(\d{2})(\d{2})/) || []
      return parts.join('-') + ' 00:00:00'
    }
  },
  data () {
    return {
      mode: 'multiple',
      showOps: true,
      selectSpanRow: true,
      data: [
        {
          id: '3154',
          name: 'Steve Rogers',
          bid: 1024,
          updateDate: '20131117',
          group: '1577'
        },
        {
          id: '3155',
          name: 'Thor Odinson',
          bid: 598,
          updateDate: '20140214',
          group: '1577'
        },
        {
          id: '3156',
          name: 'Tony Stark',
          bid: 820,
          updateDate: '20170610',
          group: '1578'
        },
        {
          id: '3157',
          name: 'Stephen Strange',
          bid: 736,
          updateDate: '20180109',
          group: '1578'
        }
      ],
      nextId: 3158,
      nextIndex: 4,
      order: false,
      orderBy: null,
      selected: ['1577'],
      groupSpan: i => {
        let groups = groupBy(this.data, 'group')
        let item = this.data[i]
        let itemGroup = groups[item.group]
        if (item.id === (itemGroup[0] || {}).id) {
          return {
            row: itemGroup.length
          }
        }
        return {
          row: 0
        }
      }
    }
  },
  computed: {
    total () {
      return this.data.reduce((total, item) => {
        return total + item.bid
      }, 0)
    }
  },
  methods: {
    del (index) {
      this.data.splice(index, 1)
    },
    append () {
      let d = new Date(Date.now() + Math.floor(Math.random() * 1e10))

      let item = {
        id: String(this.nextId),
        group: String(Math.floor(this.nextId / 2)),
        name: `Character-${this.nextIndex}`,
        bid: Math.floor(Math.random() * 1280),
        updateDate:
          d.getFullYear() +
          String(d.getMonth() + 1).padStart(2, '0') +
          String(d.getMonth() + 1).padStart(2, '0')
      }
      this.nextId++
      this.nextIndex++
      this.data.push(item)
    },
    handleSort (orderBy, order) {
      this.orderBy = orderBy
      this.order = order
    }
  }
}
</script>

<style lang="less" scoped>
section {
  margin-bottom: 20px;
}

.veui-checkbox {
  margin-right: 20px;
}
</style>

Scroll inside

Allow table content to be scrollable inside the table body, i.e. the effect of fixed head/foot.

3154
Steve Rogers
¥1024.00
2013-11-17
3155
Thor Odinson
¥598.00
2014-02-14
3156
Tony Stark
¥820.00
2017-06-10
3157
Stephen Strange
¥736.00
2018-01-09
3158
Natalie Romanoff
¥736.00
2018-01-23
3159
Bruce Banner
¥736.00
2018-12-01
3160
Peter Parker
¥736.00
2018-11-13
3161
T'Challa
¥736.00
2018-07-30
3162
Loki
¥736.00
2018-06-01
<template>
<article>
  <section>
    <veui-table
      :data="data"
      scroll="360"
      key-field="id"
    >
      <veui-table-column
        field="id"
        title="ID"
      />
      <veui-table-column
        field="name"
        title="Name"
      />
      <veui-table-column
        field="bid"
        title="Bid"
        width="160"
        align="right"
      >
        <template slot-scope="{ bid }">
          {{ bid | currency }}
        </template>
      </veui-table-column>
      <veui-table-column
        field="updateDate"
        title="Last updated"
        align="center"
      >
        <template slot-scope="{ updateDate }"></template>
      </veui-table-column>
    </veui-table>
  </section>
</article>
</template>

<script>
import { Table, Column } from 'veui'

export default {
  components: {
    'veui-table': Table,
    'veui-table-column': Column
  },
  filters: {
    currency (value) {
      return '¥' + value.toFixed(2)
    },
    date (value) {
      let [, ...parts] = value.match(/(\d{4})(\d{2})(\d{2})/) || []
      return parts.join('-')
    }
  },
  data () {
    return {
      data: [
        {
          id: '3154',
          name: 'Steve Rogers',
          bid: 1024,
          updateDate: '20131117'
        },
        {
          id: '3155',
          name: 'Thor Odinson',
          bid: 598,
          updateDate: '20140214'
        },
        {
          id: '3156',
          name: 'Tony Stark',
          bid: 820,
          updateDate: '20170610'
        },
        {
          id: '3157',
          name: 'Stephen Strange',
          bid: 736,
          updateDate: '20180109'
        },
        {
          id: '3158',
          name: 'Natalie Romanoff',
          bid: 736,
          updateDate: '20180123'
        },
        {
          id: '3159',
          name: 'Bruce Banner',
          bid: 736,
          updateDate: '20181201'
        },
        {
          id: '3160',
          name: 'Peter Parker',
          bid: 736,
          updateDate: '20181113'
        },
        {
          id: '3161',
          name: "T'Challa",
          bid: 736,
          updateDate: '20180730'
        },
        {
          id: '3162',
          name: 'Loki',
          bid: 736,
          updateDate: '20180601'
        }
      ]
    }
  }
}
</script>

<style lang="less" scoped>
section {
  margin-bottom: 20px;
}
</style>

Expandable row

Rows can be expanded into sub-rows.

ID
Name
Bid
Last updated
3154
Steve Rogers
¥1024.00
2013-11-17
3155
Thor Odinson
¥598.00
2014-02-14
3156
Tony Stark
¥820.00
2017-06-10
3157
Stephen Strange
¥736.00
2018-01-09
<template>
<article>
  <section>
    <veui-table
      :data="data"
      expandable
      key-field="id"
    >
      <veui-table-column
        field="id"
        title="ID"
      />
      <veui-table-column
        field="name"
        title="Name"
      />
      <veui-table-column
        field="bid"
        title="Bid"
        width="160"
        align="right"
      >
        <template slot-scope="{ bid }">
          {{ bid | currency }}
        </template>
      </veui-table-column>
      <veui-table-column
        field="updateDate"
        title="Last updated"
        align="center"
      >
        <template slot-scope="{ updateDate }"></template>
      </veui-table-column>
    </veui-table>
  </section>
</article>
</template>

<script>
import { Table, Column } from 'veui'

export default {
  components: {
    'veui-table': Table,
    'veui-table-column': Column
  },
  filters: {
    currency (value) {
      return '¥' + value.toFixed(2)
    },
    date (value) {
      let [, ...parts] = value.match(/(\d{4})(\d{2})(\d{2})/) || []
      return parts.join('-')
    }
  },
  data () {
    return {
      data: [
        {
          id: '3154',
          name: 'Steve Rogers',
          bid: 1024,
          updateDate: '20131117',
          children: [
            {
              id: '3154',
              name: 'Steve Rogers',
              bid: 1024,
              updateDate: '20131117'
            },
            {
              id: '3154',
              name: 'Steve Rogers',
              bid: 1001,
              updateDate: '20131116'
            },
            {
              id: '3154',
              name: 'Steve Rogers',
              bid: 985,
              updateDate: '20131115'
            }
          ]
        },
        {
          id: '3155',
          name: 'Thor Odinson',
          bid: 598,
          updateDate: '20140214',
          children: [
            {
              id: '3155',
              name: 'Thor Odinson',
              bid: 520,
              updateDate: '20131116'
            }
          ]
        },
        {
          id: '3156',
          name: 'Tony Stark',
          bid: 820,
          updateDate: '20170610',
          children: [
            {
              id: '3156',
              name: 'Tony Stark',
              bid: 800,
              updateDate: '20131116'
            },
            { id: '3156', name: 'Tony Stark', bid: 763, updateDate: '20131115' }
          ]
        },
        {
          id: '3157',
          name: 'Stephen Strange',
          bid: 736,
          updateDate: '20180109',
          children: [
            {
              id: '3157',
              name: 'Stephen Strange',
              bid: 704,
              updateDate: '20131116'
            },
            {
              id: '3157',
              name: 'Stephen Strange',
              bid: 666,
              updateDate: '20131112'
            },
            {
              id: '3157',
              name: 'Stephen Strange',
              bid: 521,
              updateDate: '20131111'
            },
            {
              id: '3157',
              name: 'Stephen Strange',
              bid: 428,
              updateDate: '20131110'
            }
          ]
        }
      ]
    }
  }
}
</script>

<style lang="less" scoped>
section {
  margin-bottom: 20px;
}
</style>

API

Props

NameTypeDefaultDescription
uistring=-

Style variants.

ValueDescription
altAlternative style.
borderedWith bordered cells.
slimSlim style.
dataArray<Object>-Table data in rows.
key-fieldstring-Denotes the unique key of the table data. The value should be a key defined in the data object of each row. The corresponding field will be regarded as the key attribute for each row element. When selectable is true, it also indicates the rows of which column should be selected from (and in this occasion the value should be defined as the field prop for one of the children Column components).
selectablebooleanfalseWhether the rows are selectable.
select-modestring'multiple'The mode of row selection. Available values are single/multiple, which denote single selection and multiple selection respectively.
selectedArray<*>|*[]

.sync

The value(s) of selected rows. When select-mode is 'multiple', the value is an array of values keyed by key-field prop from the row data . When select-mode is 'single', the value is such key value of the selected row.

expandablebooleanfalseWhether the rows can be expanded into sub-rows.
expandedArray<*>[]

.sync

The values of expanded rows. Each item is the value keyed by the key-field prop from the row data.

orderstring|booleanfalseThe order for sorting the specified column. false denotes no specific order, while string values of 'asc'/'desc' denote ascending/descending order respectively.
order-bystring-The column which is currently sorted by. The value should be defined as the field prop for one of the children Column components.
scrollnumber-The maximun height of the scrollable area inside the table body. When table content exceeds the specified height, internal scroll will be enabled and the head/foot will become fixed.

Slots

NameDescription
defaultThe columns of the table. Can only have Column components as children.
no-dataThe content to be displayed when there's no data to show.
footThe content of the table foot. Will span across all columns when defined.
sub-row

The content of the expanded sub-row. Will span across all columns and override the sub-row slot of the Column components inside the table.

The slot scope properties are the same as each item inside datasource, with an extra index: number, which denotes the index within the datasource.

Events

NameDescription
select

Triggered when the selected item(s) are changed. The callback parameter list is (selected, item, selectedItems).

NameTypeDescription
selectedbooleanWhether the item is selected after change.
itemObjectThe item in the data prop that is being selected/unselected. When it involves row span for the key-field mapped column, the data of the first related row is returned.
selectedItemsObject<string, Object|Array>All selected items as an object. The key is key-field mapped value for the selected row and the value is the row data. When it involves row span for the key-field mapped column, returns an array of row data of all related rows.
sort

Triggered when users sort a specific column. The callback parameter list is (field, order).

NameTypeDescription
fieldstringWhich column to be sort by. The value should be defined as the field prop for one of the children Column components.
orderstring|booleanSame as the order prop.