Skip to content

Table

A table component for displaying structured list data.

Basic Usage

Name
Age
Date of Birth
Address
John Brown
18
1990-04-22
New York No. 1 Lake Park
Jim Green
25
1990-11-11
London No. 1 Lake Park
Joe Black
30
1985-02-05
Sydney No. 1 Lake Park
Jon Snow
26
1993-07-11
Ottawa No. 2 Lake Park
Jim Raynor
33
1999-12-12
Moscow No. 3 Lake Park
<template>
  <b-table :columns="columns" :data="data">
    <template #age="{ row }">
      <b-tag>{{ row.age }}</b-tag>
    </template>
  </b-table>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const columns = [
  { title: 'Name', key: 'name' },
  { title: 'Age', slot: 'age' },
  { title: 'Date of Birth', key: 'birthday' },
  { title: 'Address', key: 'address' }
]
const data = ref([
  {
    name: 'John Brown',
    age: 18,
    birthday: '1990-04-22',
    address: 'New York No. 1 Lake Park'
  },
  {
    name: 'Jim Green',
    age: 25,
    birthday: '1990-11-11',
    address: 'London No. 1 Lake Park'
  },
  {
    name: 'Joe Black',
    age: 30,
    birthday: '1985-02-05',
    address: 'Sydney No. 1 Lake Park'
  },
  {
    name: 'Jon Snow',
    age: 26,
    birthday: '1993-07-11',
    address: 'Ottawa No. 2 Lake Park'
  },
  {
    name: 'Jim Raynor',
    age: 33,
    birthday: '1999-12-12',
    address: 'Moscow No. 3 Lake Park'
  }
])
</script>

Striped Rows

Set stripe to enable alternating row colors.

Name
Age
Date of Birth
Address
John Brown
18
1990-04-22
New York No. 1 Lake Park
Jim Green
25
1990-11-11
London No. 1 Lake Park
Joe Black
30
1985-02-05
Sydney No. 1 Lake Park
Jon Snow
26
1993-07-11
Ottawa No. 2 Lake Park
Jim Raynor
33
1999-12-12
Moscow No. 3 Lake Park
<template>
  <b-table :columns="columns" :data="data" stripe>
    <template #age="{ row }">
      <b-tag>{{ row.age }}</b-tag>
    </template>
  </b-table>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const columns = [
  { title: 'Name', key: 'name' },
  { title: 'Age', slot: 'age' },
  { title: 'Date of Birth', key: 'birthday' },
  { title: 'Address', key: 'address' }
]
const data = ref([
  {
    name: 'John Brown',
    age: 18,
    birthday: '1990-04-22',
    address: 'New York No. 1 Lake Park'
  },
  {
    name: 'Jim Green',
    age: 25,
    birthday: '1990-11-11',
    address: 'London No. 1 Lake Park'
  },
  {
    name: 'Joe Black',
    age: 30,
    birthday: '1985-02-05',
    address: 'Sydney No. 1 Lake Park'
  },
  {
    name: 'Jon Snow',
    age: 26,
    birthday: '1993-07-11',
    address: 'Ottawa No. 2 Lake Park'
  },
  {
    name: 'Jim Raynor',
    age: 33,
    birthday: '1999-12-12',
    address: 'Moscow No. 3 Lake Park'
  }
])
</script>

Border

Set border to enable vertical borders.

Name
Age
Date of Birth
Address
John Brown
18
1990-04-22
New York No. 1 Lake Park
Jim Green
25
1990-11-11
London No. 1 Lake Park
Joe Black
30
1985-02-05
Sydney No. 1 Lake Park
Jon Snow
26
1993-07-11
Ottawa No. 2 Lake Park
Jim Raynor
33
1999-12-12
Moscow No. 3 Lake Park
<template>
  <b-table :columns="columns" :data="data" border>
    <template #age="{ row }">
      <b-tag>{{ row.age }}</b-tag>
    </template>
  </b-table>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const columns = [
  { title: 'Name', key: 'name' },
  { title: 'Age', slot: 'age' },
  { title: 'Date of Birth', key: 'birthday' },
  { title: 'Address', key: 'address' }
]
const data = ref([
  {
    name: 'John Brown',
    age: 18,
    birthday: '1990-04-22',
    address: 'New York No. 1 Lake Park'
  },
  {
    name: 'Jim Green',
    age: 25,
    birthday: '1990-11-11',
    address: 'London No. 1 Lake Park'
  },
  {
    name: 'Joe Black',
    age: 30,
    birthday: '1985-02-05',
    address: 'Sydney No. 1 Lake Park'
  },
  {
    name: 'Jon Snow',
    age: 26,
    birthday: '1993-07-11',
    address: 'Ottawa No. 2 Lake Park'
  },
  {
    name: 'Jim Raynor',
    age: 33,
    birthday: '1999-12-12',
    address: 'Moscow No. 3 Lake Park'
  }
])
</script>

Text Overflow Tooltip

Set tooltip on a column to truncate long text and show the full content on hover. If there is only one table on the page, you can also set tooltip-theme for a more polished tooltip style.

Note: Columns with tooltip enabled should use a fixed width such as width; otherwise text truncation and tooltip alignment may become inconsistent in auto-width layouts.

Note: Table cells use overflow: hidden, so tooltip nodes must be appended to body. When many table instances are cached at the same time, this can create extra nodes and affect performance, so enable it only when needed.

Default原生title
Name
Age
Birthday
Address
Remarks
王小明
18
1990-04-22
BeijingCity朝阳区芍药居
这是一段描述文字,文本长度会超出Column宽,设置tooltipproperty可以设置不换Rowshow并开启mousehovershow所有文字。
张小刚
25
1990-11-11
BeijingCity海淀区西二旗
这是一段描述文字,文本长度会超出Column宽,设置tooltipproperty可以设置不换Rowshow并开启mousehovershow所有文字。
李小红
30
1985-02-05
ShanghaiCity浦东New区世纪大道
这是一段描述文字,文本长度会超出Column宽,设置tooltipproperty可以设置不换Rowshow并开启mousehovershow所有文字。
周小伟
26
1993-07-11
ShenzhenCity南山区深南大道
这是一段描述文字,文本长度会超出Column宽,设置tooltipproperty可以设置不换Rowshow并开启mousehovershow所有文字。
张小发
33
1999-12-12
NanjingCity龙眠大道
这是一段描述文字,文本长度会超出Column宽,设置tooltipproperty可以设置不换Rowshow并开启mousehovershow所有文字。
开启tooltip
Name
Age
Birthday
Address
Remarks
王小明
18
1990-04-22
BeijingCity朝阳区芍药居
这是一段描述文字,文本长度会超出Column宽,设置tooltipproperty可以设置不换Rowshow并开启mousehovershow所有文字。
张小刚
25
1990-11-11
BeijingCity海淀区西二旗
这是一段描述文字,文本长度会超出Column宽,设置tooltipproperty可以设置不换Rowshow并开启mousehovershow所有文字。
李小红
30
1985-02-05
ShanghaiCity浦东New区世纪大道
这是一段描述文字,文本长度会超出Column宽,设置tooltipproperty可以设置不换Rowshow并开启mousehovershow所有文字。
周小伟
26
1993-07-11
ShenzhenCity南山区深南大道
这是一段描述文字,文本长度会超出Column宽,设置tooltipproperty可以设置不换Rowshow并开启mousehovershow所有文字。
张小发
33
1999-12-12
NanjingCity龙眠大道
这是一段描述文字,文本长度会超出Column宽,设置tooltipproperty可以设置不换Rowshow并开启mousehovershow所有文字。
<template>
  <div>
    <b-divider align="left">Default原生title</b-divider>
    <b-table :columns="columns" :data="data" border></b-table>
    <b-divider align="left">开启tooltip</b-divider>
    <b-table :columns="columns" :data="data" border tooltip-theme="dark"></b-table>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const columns = [
  { title: 'Name', key: 'name' },
  { title: 'Age', key: 'age' },
  { title: 'Birthday', key: 'birthday' },
  { title: 'Address', key: 'address' },
  { title: 'Remarks', key: 'remark', width: 300, tooltip: true }
]
const data = ref([
  {
    name: '王小明',
    age: 18,
    birthday: '1990-04-22',
    address: 'BeijingCity朝阳区芍药居',
    remark:
      '这是一段描述文字,文本长度会超出Column宽,设置tooltipproperty可以设置不换Rowshow并开启mousehovershow所有文字。'
  },
  {
    name: '张小刚',
    age: 25,
    birthday: '1990-11-11',
    address: 'BeijingCity海淀区西二旗',
    remark:
      '这是一段描述文字,文本长度会超出Column宽,设置tooltipproperty可以设置不换Rowshow并开启mousehovershow所有文字。'
  },
  {
    name: '李小红',
    age: 30,
    birthday: '1985-02-05',
    address: 'ShanghaiCity浦东New区世纪大道',
    remark:
      '这是一段描述文字,文本长度会超出Column宽,设置tooltipproperty可以设置不换Rowshow并开启mousehovershow所有文字。'
  },
  {
    name: '周小伟',
    age: 26,
    birthday: '1993-07-11',
    address: 'ShenzhenCity南山区深南大道',
    remark:
      '这是一段描述文字,文本长度会超出Column宽,设置tooltipproperty可以设置不换Rowshow并开启mousehovershow所有文字。'
  },
  {
    name: '张小发',
    age: 33,
    birthday: '1999-12-12',
    address: 'NanjingCity龙眠大道',
    remark:
      '这是一段描述文字,文本长度会超出Column宽,设置tooltipproperty可以设置不换Rowshow并开启mousehovershow所有文字。'
  }
])
</script>

Fixed Header

Use height or max-height to fix the table header. The table body scrolls through the built-in scrollbar, and fixed columns stay in sync with the body scroll position.

Name
Age
Birthday
Address
王小明
18
1990-04-22
BeijingCity朝阳区芍药居
张小刚
25
1990-11-11
BeijingCity海淀区西二旗
李小红
30
1985-02-05
ShanghaiCity浦东New区世纪大道
周小伟
26
1993-07-11
ShenzhenCity南山区深南大道
张小发
33
1999-12-12
NanjingCity龙眠大道
<template>
  <b-table :columns="columns" :data="data" height="200" border></b-table>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const columns = [
  { title: 'Name', key: 'name' },
  { title: 'Age', key: 'age' },
  { title: 'Birthday', key: 'birthday' },
  { title: 'Address', key: 'address' }
]
const data = ref([
  {
    name: '王小明',
    age: 18,
    birthday: '1990-04-22',
    address: 'BeijingCity朝阳区芍药居'
  },
  {
    name: '张小刚',
    age: 25,
    birthday: '1990-11-11',
    address: 'BeijingCity海淀区西二旗'
  },
  {
    name: '李小红',
    age: 30,
    birthday: '1985-02-05',
    address: 'ShanghaiCity浦东New区世纪大道'
  },
  {
    name: '周小伟',
    age: 26,
    birthday: '1993-07-11',
    address: 'ShenzhenCity南山区深南大道'
  },
  {
    name: '张小发',
    age: 33,
    birthday: '1999-12-12',
    address: 'NanjingCity龙眠大道'
  }
])
</script>

Fixed Header and Columns

Both header and columns can be fixed simultaneously.

Name
Age
Birthday
Address
Actions
王小明
18
1990-04-22
BeijingCity朝阳区芍药居
张小刚
25
1990-11-11
BeijingCity海淀区西二旗
李小红
30
1985-02-05
ShanghaiCity浦东New区世纪大道
周小伟
26
1993-07-11
ShenzhenCity南山区深南大道
张小发
33
1999-12-12
NanjingCity龙眠大道
Name
王小明
张小刚
李小红
周小伟
张小发
<template>
  <div style="width: 800px">
    <b-table :columns="columns" :data="data" height="200" border></b-table>
  </div>
</template>

<script setup lang="ts">
import { ref, h } from 'vue'

const columns = [
  {
    title: 'Name',
    fixed: 'left',
    key: 'name',
    width: 150
  },
  {
    title: 'Age',
    key: 'age',
    width: 150
  },
  {
    title: 'Birthday',
    key: 'birthday',
    width: 150
  },
  {
    title: 'Address',
    key: 'address',
    width: 350
  },
  {
    title: 'Actions',
    fixed: 'right',
    width: 100,
    render: () => {
      return h('a', { style: { cursor: 'pointer' } }, 'Edit')
    }
  }
]

const data = ref([
  {
    name: '王小明',
    age: 18,
    birthday: '1990-04-22',
    address: 'BeijingCity朝阳区芍药居'
  },
  {
    name: '张小刚',
    age: 25,
    birthday: '1990-11-11',
    address: 'BeijingCity海淀区西二旗'
  },
  {
    name: '李小红',
    age: 30,
    birthday: '1985-02-05',
    address: 'ShanghaiCity浦东New区世纪大道'
  },
  {
    name: '周小伟',
    age: 26,
    birthday: '1993-07-11',
    address: 'ShenzhenCity南山区深南大道'
  },
  {
    name: '张小发',
    age: 33,
    birthday: '1999-12-12',
    address: 'NanjingCity龙眠大道'
  }
])
</script>

Auto Height

Name
Age
Birthday
Address
Actions
王小明
18
1990-04-22
BeijingCity朝阳区芍药居
张小刚
25
1990-11-11
BeijingCity海淀区西二旗

<template>
  <div style="padding: 2px">
    <b-table :columns="columns" :data="data" max-height="200" border>
      <template #ctrl="{ index }">
        <b-button type="danger" size="mini" plain @click="removeRow(index)">Delete</b-button>
      </template>
    </b-table>
    <br />
    <b-button @click="add">增加一条数据</b-button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const columns = [
  { title: 'Name', key: 'name' },
  { title: 'Age', key: 'age', align: 'center' },
  { title: 'Birthday', key: 'birthday' },
  { title: 'Address', key: 'address', width: 350 },
  { title: 'Actions', slot: 'ctrl', width: 100 }
]
const data = ref([
  {
    name: '王小明',
    age: 18,
    birthday: '1990-04-22',
    address: 'BeijingCity朝阳区芍药居'
  },
  {
    name: '张小刚',
    age: 25,
    birthday: '1990-11-11',
    address: 'BeijingCity海淀区西二旗'
  }
])

function add() {
  data.value.push({
    name: '张小发',
    age: 33,
    birthday: '1999-12-12',
    address: 'NanjingCity龙眠大道'
  })
}
function removeRow(index) {
  data.value.splice(index, 1)
}
</script>

Single Selection

Name
Age
Birthday
Address
王小明
18
1990-04-22
BeijingCity朝阳区芍药居
张小刚
25
1990-11-11
BeijingCity海淀区西二旗
李小红
30
1985-02-05
ShanghaiCity浦东New区世纪大道
周小伟
26
1993-07-11
ShenzhenCity南山区深南大道
张小发
33
1999-12-12
NanjingCity龙眠大道


Name
Age
Birthday
Address
Actions
王小明
18
1990-04-22
BeijingCity朝阳区芍药居
张小刚
25
1990-11-11
BeijingCity海淀区西二旗
李小红
30
1985-02-05
ShanghaiCity浦东New区世纪大道
周小伟
26
1993-07-11
ShenzhenCity南山区深南大道
张小发
33
1999-12-12
NanjingCity龙眠大道

<template>
  <div>
    <b-table
      ref="currentRowTable"
      :columns="columns"
      :data="data"
      highlight-row
      highlight-row-cancel
      @current-change="currentRowChange"
    ></b-table>
    <br />
    <div>
      <b-button @click="clearSelect">清除Single select</b-button>
      <b-button @click="clickRow(0)">select第一Row</b-button>
    </div>
    <br />
    <b-table
      ref="currentRowTable2"
      :columns="columns2"
      :data="data2"
      highlight-row
      @current-change="currentRowChange"
    >
      <template #ctrl="{ index }">
        <b-button type="text" text-color="danger" @click="removeRow(index)">Delete</b-button>
      </template>
    </b-table>
    <br />
    <b-button @click="init">初始化table2并Defaultselect第一Row</b-button>
  </div>
</template>

<script setup lang="ts">
import { ref, nextTick } from 'vue'
import { Message } from 'bin-ui-design'

const columns = [
  { title: 'Name', key: 'name' },
  { title: 'Age', key: 'age' },
  { title: 'Birthday', key: 'birthday' },
  { title: 'Address', key: 'address' }
]
const columns2 = [
  { title: 'Name', key: 'name' },
  { title: 'Age', key: 'age' },
  { title: 'Birthday', key: 'birthday' },
  { title: 'Address', key: 'address' },
  { title: 'Actions', slot: 'ctrl' }
]
const data = ref([
  {
    name: '王小明',
    age: 18,
    birthday: '1990-04-22',
    address: 'BeijingCity朝阳区芍药居'
  },
  {
    name: '张小刚',
    age: 25,
    birthday: '1990-11-11',
    address: 'BeijingCity海淀区西二旗'
  },
  {
    name: '李小红',
    age: 30,
    birthday: '1985-02-05',
    address: 'ShanghaiCity浦东New区世纪大道'
  },
  {
    name: '周小伟',
    age: 26,
    birthday: '1993-07-11',
    address: 'ShenzhenCity南山区深南大道'
  },
  {
    name: '张小发',
    age: 33,
    birthday: '1999-12-12',
    address: 'NanjingCity龙眠大道'
  }
])
const data2 = ref([
  {
    name: '王小明',
    age: 18,
    birthday: '1990-04-22',
    address: 'BeijingCity朝阳区芍药居'
  },
  {
    name: '张小刚',
    age: 25,
    birthday: '1990-11-11',
    address: 'BeijingCity海淀区西二旗'
  },
  {
    name: '李小红',
    age: 30,
    birthday: '1985-02-05',
    address: 'ShanghaiCity浦东New区世纪大道'
  },
  {
    name: '周小伟',
    age: 26,
    birthday: '1993-07-11',
    address: 'ShenzhenCity南山区深南大道'
  },
  {
    name: '张小发',
    age: 33,
    birthday: '1999-12-12',
    address: 'NanjingCity龙眠大道'
  }
])
const currentRowTable = ref(null)
const currentRowTable2 = ref(null)

function currentRowChange(currentRow, oldRow, index) {
  console.log(currentRow, oldRow, index)
  if (index >= 0) {
    Message(`select了第${index + 1}Row`)
  }
}

function clearSelect() {
  currentRowTable.value.clearCurrentRow()
}
// select某一Row
function clickRow(index) {
  currentRowTable.value.clickCurrentRow(index)
}
function init() {
  data2.value = JSON.parse(JSON.stringify(data.value))
  nextTick(() => {
    currentRowTable2.value.clickCurrentRow(0)
  })
}
function removeRow(index) {
  data2.value.splice(index, 1)
}
</script>

Multiple Selection

Enable multi-selection by adding a column with type: 'selection'.

Set the special key _checked: true on a data row to pre-select it.

Set the special key _disabled: true on a data row to disable its selection.

@select: triggers when a row is selected. Returns selection and row — the selected rows and the most recently selected row. @select-all: triggers when all items are selected. Returns selection — all selected rows. @selection-change: triggers whenever the selection changes. Returns selection — all selected rows.

Name
Age
Birthday
Address
王小明
18
1990-04-22
BeijingCity朝阳区芍药居
张小刚
25
1990-11-11
BeijingCity海淀区西二旗
李小红
30
1985-02-05
ShanghaiCity浦东New区世纪大道
周小伟
26
1993-07-11
ShenzhenCity南山区深南大道
张小发
33
1999-12-12
NanjingCity龙眠大道

<template>
  <div>
    <b-table ref="tableRef" :columns="columns" :data="data" highlight-row></b-table>
    <br />
    <b-button @click="$refs.tableRef.selectAll(true)">设置全选</b-button>
    <b-button @click="$refs.tableRef.selectAll(false)">Cancel全选</b-button>
    <b-button @click="getAllSelected">获取select</b-button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const columns = [
  { type: 'selection', width: 60, align: 'center' },
  { title: 'Name', key: 'name' },
  { title: 'Age', key: 'age' },
  { title: 'Birthday', key: 'birthday' },
  { title: 'Address', key: 'address' }
]
const data = ref([
  {
    name: '王小明',
    age: 18,
    birthday: '1990-04-22',
    address: 'BeijingCity朝阳区芍药居'
  },
  {
    name: '张小刚',
    age: 25,
    birthday: '1990-11-11',
    address: 'BeijingCity海淀区西二旗'
  },
  {
    name: '李小红',
    age: 30,
    birthday: '1985-02-05',
    address: 'ShanghaiCity浦东New区世纪大道'
  },
  {
    name: '周小伟',
    age: 26,
    birthday: '1993-07-11',
    address: 'ShenzhenCity南山区深南大道'
  },
  {
    name: '张小发',
    age: 33,
    birthday: '1999-12-12',
    address: 'NanjingCity龙眠大道'
  }
])
const tableRef = ref(null)
function getAllSelected() {
  const selected = tableRef.value.getSelection()
  console.log(selected)
}
</script>

Expandable Rows

Enable expandable rows by adding a column with type: 'expand'.

Name
Age
Date of Birth
Detailed Address
John Brown
18
1990-04-22
New York No. 1 Lake Park
Jim Green
25
1990-11-11
London No. 1 Lake Park
Joe Black
30
1985-02-05
Sydney No. 1 Lake Park
Jon Snow
26
1993-07-11
Ottawa No. 2 Lake Park
Jim Raynor
33
1999-12-12
Moscow No. 3 Lake Park
<template>
  <b-table :columns="columns" :data="data"></b-table>
</template>

<script setup lang="ts">
import { ref, h } from 'vue'
const columns = [
  {
    type: 'expand',
    width: 50,
    render: params => {
      return h('div', 'Detailed Address: ' + params.row.address)
    }
  },
  { title: 'Name', key: 'name' },
  { title: 'Age', key: 'age' },
  { title: 'Date of Birth', key: 'birthday' },
  { title: 'Detailed Address', key: 'address' }
]

const data = ref([
  {
    name: 'John Brown',
    age: 18,
    birthday: '1990-04-22',
    address: 'New York No. 1 Lake Park'
  },
  {
    name: 'Jim Green',
    age: 25,
    birthday: '1990-11-11',
    address: 'London No. 1 Lake Park'
  },
  {
    name: 'Joe Black',
    age: 30,
    birthday: '1985-02-05',
    address: 'Sydney No. 1 Lake Park'
  },
  {
    name: 'Jon Snow',
    age: 26,
    birthday: '1993-07-11',
    address: 'Ottawa No. 2 Lake Park'
  },
  {
    name: 'Jim Raynor',
    age: 33,
    birthday: '1999-12-12',
    address: 'Moscow No. 3 Lake Park'
  }
])
</script>

Tree Table

Tree table mode always uses children as the nested field. It is enabled only when row-key is a string and expand-column-key is also provided.

Supports:

  • default-expanded-row-keys for uncontrolled default expansion
  • expanded-row-keys + @update:expanded-row-keys for controlled expansion
  • Sorting within sibling groups while preserving the tree hierarchy
  • Fixed columns and fixed-height scrolling

Current limits:

  • Not supported together with type: 'expand'
  • Not supported together with draggable
  • Not recommended together with mergeMethod

The first table expands East China by default. The second table shows controlled expanded keys with fixed columns.

Department / Member
City
Monthly Deals
East China
Shanghai
286
Retail Team
Shanghai
168
Channel Team
Hangzhou
118
South China
Shenzhen
214
Expanded keys: 1001
Department / Member
City
Role
Monthly Deals
Status
East China
Shanghai
Region
286
Stable
Retail Team
Shanghai
Team
168
Stable
Channel Team
Hangzhou
Team
118
Stable
South China
Shenzhen
Region
214
Stable
Department / Member
East China
Retail Team
Channel Team
South China
Status
Stable
Stable
Stable
Stable
<template>
  <div>
    <p class="mb-12">
      The first table expands East China by default. The second table shows controlled
      expanded keys with fixed columns.
    </p>

    <b-table
      class="mb-24"
      border
      :columns="basicColumns"
      :data="treeData"
      row-key="id"
      expand-column-key="name"
      :default-expanded-row-keys="[1001]"
    ></b-table>

    <div class="mb-12">
      <b-button size="small" @click="expandedRowKeys = [1001, 1002]">Expand all</b-button>
      <b-button size="small" class="ml-8" @click="expandedRowKeys = []">Collapse all</b-button>
      <b-button size="small" class="ml-8" @click="expandedRowKeys = [1001]">
        Reset default
      </b-button>
    </div>
    <div class="mb-12">Expanded keys: {{ expandedRowKeys.join(', ') || '-' }}</div>

    <b-table
      border
      height="260"
      :columns="fixedColumns"
      :data="treeData"
      row-key="id"
      expand-column-key="name"
      :expanded-row-keys="expandedRowKeys"
      @update:expanded-row-keys="expandedRowKeys = $event"
    ></b-table>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const basicColumns = [
  {
    title: 'Department / Member',
    key: 'name',
    minWidth: 220
  },
  {
    title: 'City',
    key: 'city',
    minWidth: 140
  },
  {
    title: 'Monthly Deals',
    key: 'amount',
    width: 140,
    sortable: true
  }
]

const fixedColumns = [
  {
    title: 'Department / Member',
    key: 'name',
    minWidth: 220,
    fixed: 'left'
  },
  {
    title: 'City',
    key: 'city',
    minWidth: 140
  },
  {
    title: 'Role',
    key: 'role',
    minWidth: 140
  },
  {
    title: 'Monthly Deals',
    key: 'amount',
    width: 140,
    sortable: true
  },
  {
    title: 'Status',
    key: 'status',
    width: 120,
    fixed: 'right'
  }
]

const treeData = [
  {
    id: 1001,
    name: 'East China',
    city: 'Shanghai',
    role: 'Region',
    amount: 286,
    status: 'Stable',
    children: [
      {
        id: 1101,
        name: 'Retail Team',
        city: 'Shanghai',
        role: 'Team',
        amount: 168,
        status: 'Stable',
        children: [
          {
            id: 1111,
            name: 'Mia Wang',
            city: 'Shanghai',
            role: 'Sales',
            amount: 92,
            status: 'Active'
          },
          {
            id: 1112,
            name: 'Iris Li',
            city: 'Suzhou',
            role: 'Sales',
            amount: 76,
            status: 'Active'
          }
        ]
      },
      {
        id: 1102,
        name: 'Channel Team',
        city: 'Hangzhou',
        role: 'Team',
        amount: 118,
        status: 'Stable',
        children: [
          {
            id: 1121,
            name: 'Noah Zhou',
            city: 'Hangzhou',
            role: 'Sales',
            amount: 63,
            status: 'Following up'
          },
          {
            id: 1122,
            name: 'Lena Chen',
            city: 'Ningbo',
            role: 'Sales',
            amount: 55,
            status: 'Following up'
          }
        ]
      }
    ]
  },
  {
    id: 1002,
    name: 'South China',
    city: 'Shenzhen',
    role: 'Region',
    amount: 214,
    status: 'Stable',
    children: [
      {
        id: 1201,
        name: 'Customer Success',
        city: 'Shenzhen',
        role: 'Team',
        amount: 126,
        status: 'Stable',
        children: [
          {
            id: 1211,
            name: 'Leo Zhang',
            city: 'Shenzhen',
            role: 'Sales',
            amount: 74,
            status: 'Active'
          },
          {
            id: 1212,
            name: 'Evan Zhao',
            city: 'Guangzhou',
            role: 'Sales',
            amount: 52,
            status: 'Active'
          }
        ]
      }
    ]
  }
]

const expandedRowKeys = ref([1001])
</script>

Grouped Header

Use children in column definitions to group table headers. For merged headers and cells, the border mode is recommended.

Name
基本Info
EducationInfo
Age
Birthday
详细Address
毕业院校
毕业Day期
王小明
18
1990-04-22
BeijingCity朝阳区芍药居
Nanjing河海大学
2012-04-22
张小刚
25
1990-11-11
BeijingCity海淀区西二旗
Beijing大学
2012-04-22
李小红
30
1985-02-05
ShanghaiCity浦东New区世纪大道
Shanghai复旦
2012-04-22
周小伟
26
1993-07-11
ShenzhenCity南山区深南大道
广东大学
2012-04-22
张小发
33
1999-12-12
NanjingCity龙眠大道
Nanjing交通学院
2012-04-22
李晓红
23
1999-12-12
NanjingCity龙眠大道
Nanjing交通学院
2012-04-22
郭小宁
23
1999-12-12
NanjingCity龙眠大道
Nanjing交通学院
2012-04-22
<template>
  <b-table :columns="columns" height="300" :data="data" border></b-table>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const columns = [
  { title: 'Name', key: 'name' },
  {
    title: '基本Info',
    align: 'center',
    children: [
      { title: 'Age', key: 'age' },
      { title: 'Birthday', key: 'birthday' },
      { title: '详细Address', key: 'address' }
    ]
  },
  {
    title: 'EducationInfo',
    align: 'center',
    children: [
      { title: '毕业院校', key: 'school' },
      { title: '毕业Day期', key: 'eduDate' }
    ]
  }
]
const data = ref([
  {
    name: '王小明',
    age: 18,
    birthday: '1990-04-22',
    address: 'BeijingCity朝阳区芍药居',
    school: 'Nanjing河海大学',
    eduDate: '2012-04-22'
  },
  {
    name: '张小刚',
    age: 25,
    birthday: '1990-11-11',
    address: 'BeijingCity海淀区西二旗',
    school: 'Beijing大学',
    eduDate: '2012-04-22'
  },
  {
    name: '李小红',
    age: 30,
    birthday: '1985-02-05',
    address: 'ShanghaiCity浦东New区世纪大道',
    school: 'Shanghai复旦',
    eduDate: '2012-04-22'
  },
  {
    name: '周小伟',
    age: 26,
    birthday: '1993-07-11',
    address: 'ShenzhenCity南山区深南大道',
    school: '广东大学',
    eduDate: '2012-04-22'
  },
  {
    name: '张小发',
    age: 33,
    birthday: '1999-12-12',
    address: 'NanjingCity龙眠大道',
    school: 'Nanjing交通学院',
    eduDate: '2012-04-22'
  },
  {
    name: '李晓红',
    age: 23,
    birthday: '1999-12-12',
    address: 'NanjingCity龙眠大道',
    school: 'Nanjing交通学院',
    eduDate: '2012-04-22'
  },
  {
    name: '郭小宁',
    age: 23,
    birthday: '1999-12-12',
    address: 'NanjingCity龙眠大道',
    school: 'Nanjing交通学院',
    eduDate: '2012-04-22'
  }
])
</script>

Row & Column Merging

Configure mergeMethod to specify row/column merging logic. The method parameters are four objects: row, column, rowIndex, columnIndex. The method returns an array of two elements: the first is rowspan, the second is colspan. It is recommended to use border mode for merged cells.

Name
Age
Birthday
Address
王小明
18
1990-04-22
BeijingCity朝阳区芍药居
25
1990-11-11
BeijingCity海淀区西二旗
李小红
30
1985-02-05
ShanghaiCity浦东New区世纪大道
周小伟
26
1993-07-11
张小发
33
1999-12-12
NanjingCity龙眠大道
<template>
  <b-table :columns="columns" :data="data" border :merge-method="handleSpan"></b-table>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const columns = [
  { title: 'Name', key: 'name' },
  { title: 'Age', key: 'age' },
  { title: 'Birthday', key: 'birthday' },
  { title: 'Address', key: 'address' }
]
const data = ref([
  {
    name: '王小明',
    age: 18,
    birthday: '1990-04-22',
    address: 'BeijingCity朝阳区芍药居'
  },
  {
    name: '张小刚',
    age: 25,
    birthday: '1990-11-11',
    address: 'BeijingCity海淀区西二旗'
  },
  {
    name: '李小红',
    age: 30,
    birthday: '1985-02-05',
    address: 'ShanghaiCity浦东New区世纪大道'
  },
  {
    name: '周小伟',
    age: 26,
    birthday: '1993-07-11',
    address: 'ShenzhenCity南山区深南大道'
  },
  {
    name: '张小发',
    age: 33,
    birthday: '1999-12-12',
    address: 'NanjingCity龙眠大道'
  }
])

function handleSpan({ row, column, rowIndex, columnIndex }) {
  // 获取相同Name的Row是,0,1
  if (rowIndex === 0 && columnIndex === 0) {
    return {
      rowspan: 2,
      colspan: 1
    }
  } else if (rowIndex === 1 && columnIndex === 0) {
    return {
      rowspan: 0,
      colspan: 1
    }
  }
  // 合并Column,这里将第三Row,周小伟的Day期和Address合并
  if (rowIndex === 3 && columnIndex === 2) {
    return [1, 2]
  } else if (rowIndex === 3 && columnIndex === 3) {
    return [0, 0]
  }
}
</script>

Sortable

Name
Age
Date of Birth
Address
John Brown
18
1990-04-22
New York No. 1 Lake Park
Jim Green
25
1990-11-11
London No. 1 Lake Park
Joe Black
30
1985-02-05
Sydney No. 1 Lake Park
Jon Snow
26
1993-07-11
Ottawa No. 2 Lake Park
Jim Raynor
33
1999-12-12
Moscow No. 3 Lake Park
<template>
  <b-table :columns="columns" :data="data"></b-table>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const columns = [
  { title: 'Name', key: 'name' },
  { title: 'Age', key: 'age', sortable: true },
  { title: 'Date of Birth', key: 'birthday' },
  { title: 'Address', key: 'address' }
]
const data = ref([
  {
    name: 'John Brown',
    age: 18,
    birthday: '1990-04-22',
    address: 'New York No. 1 Lake Park'
  },
  {
    name: 'Jim Green',
    age: 25,
    birthday: '1990-11-11',
    address: 'London No. 1 Lake Park'
  },
  {
    name: 'Joe Black',
    age: 30,
    birthday: '1985-02-05',
    address: 'Sydney No. 1 Lake Park'
  },
  {
    name: 'Jon Snow',
    age: 26,
    birthday: '1993-07-11',
    address: 'Ottawa No. 2 Lake Park'
  },
  {
    name: 'Jim Raynor',
    age: 33,
    birthday: '1999-12-12',
    address: 'Moscow No. 3 Lake Park'
  }
])
</script>

Inline Editing

Name
Age
Birthday
Hobby
Address
Actions
王小明
18
1990-04-22
吃饭
BeijingCity朝阳区芍药居
张小刚
25
1990-11-11
吃饭
BeijingCity海淀区西二旗
李小红
30
1985-02-05
打豆豆
ShanghaiCity浦东New区世纪大道
周小伟
26
1993-07-11
吃饭
ShenzhenCity南山区深南大道
张小发
33
1999-12-12
睡觉
NanjingCity龙眠大道
<template>
  <b-table :columns="columns" :data="data">
    <template #name="{ index, row }">
      <b-input
        v-if="obj.editIndex === index"
        v-model="obj.editName"
        type="text"
        size="small"
        clearable
      ></b-input>
      <span v-else>{{ row.name }}</span>
    </template>
    <template #age="{ index, row }">
      <b-input-number
        v-if="obj.editIndex === index"
        v-model="obj.editAge"
        type="text"
        size="small"
      ></b-input-number>
      <span v-else>{{ row.age }}</span>
    </template>
    <template #birthday="{ index, row }">
      <b-date-picker
        v-if="obj.editIndex === index"
        v-model="obj.editBirthday"
        size="small"
        type="date"
        placeholder="选择Day期"
      ></b-date-picker>
      <span v-else>{{ row.birthday }}</span>
    </template>
    <template #hobby="{ index, row }">
      <b-select v-if="obj.editIndex === index" v-model="obj.editHobby" clearable size="small">
        <b-option v-for="(val, key) in hobbyMap" :key="key" :value="key" :label="val">
          {{ val }}
        </b-option>
      </b-select>
      <span v-else>{{ hobbyMap[row.hobby] }}</span>
    </template>
    <template #address="{ index, row }">
      <b-input
        v-if="obj.editIndex === index"
        v-model="obj.editAddress"
        type="text"
        size="small"
      ></b-input>
      <span v-else>{{ row.address }}</span>
    </template>
    <template #action="{ index, row }">
      <div v-if="obj.editIndex === index">
        <b-button size="small" type="success" plain @click="handleSave(index)">save</b-button>
        <b-button size="small" @click="obj.editIndex = -1">Cancel</b-button>
      </div>
      <div v-else>
        <b-button size="small" @click="handleEdit(row, index)">Actions</b-button>
      </div>
    </template>
  </b-table>
</template>

<script setup lang="ts">
import { reactive, ref } from 'vue'
import dayjs from 'dayjs'

const columns = [
  { title: 'Name', slot: 'name' },
  { title: 'Age', slot: 'age' },
  { title: 'Birthday', slot: 'birthday' },
  { title: 'Hobby', slot: 'hobby' },
  { title: 'Address', slot: 'address' },
  { title: 'Actions', slot: 'action' }
]
const hobbyMap = { '1': '吃饭', '2': '睡觉', '3': '打豆豆' }
const data = ref([
  {
    name: '王小明',
    age: 18,
    birthday: '1990-04-22',
    hobby: '1',
    address: 'BeijingCity朝阳区芍药居'
  },
  {
    name: '张小刚',
    age: 25,
    birthday: '1990-11-11',
    hobby: '1',
    address: 'BeijingCity海淀区西二旗'
  },
  {
    name: '李小红',
    age: 30,
    birthday: '1985-02-05',
    hobby: '3',
    address: 'ShanghaiCity浦东New区世纪大道'
  },
  {
    name: '周小伟',
    age: 26,
    birthday: '1993-07-11',
    hobby: '1',
    address: 'ShenzhenCity南山区深南大道'
  },
  {
    name: '张小发',
    age: 33,
    birthday: '1999-12-12',
    hobby: '2',
    address: 'NanjingCity龙眠大道'
  }
])

const obj = reactive({
  editName: '',
  editAge: '',
  editBirthday: '',
  editHobby: '',
  editAddress: '',
  editIndex: -1
})

function handleEdit(row, index) {
  obj.editName = row.name
  obj.editAge = row.age
  obj.editHobby = row.hobby
  obj.editAddress = row.address
  obj.editBirthday = new Date(row.birthday)
  obj.editIndex = index
}
function handleSave(index) {
  data.value[index].name = obj.editName
  data.value[index].age = obj.editAge
  data.value[index].birthday = dayjs(obj.editBirthday).format('YYYY-MM-DD')
  data.value[index].hobby = obj.editHobby
  data.value[index].address = obj.editAddress
  obj.editIndex = -1
}
</script>

Edit Mode

Enable the edit table style to hide input borders, making inline table editing easier.

Edittable
Name
Age
Birthday
Hobby
Address
Readonly
Name
Age
Birthday
Hobby
Address
王小明
18
1990-04-22
吃饭
BeijingCity朝阳区芍药居
张小刚
25
1990-11-11
吃饭
BeijingCity海淀区西二旗
李小红
30
1985-02-05
打豆豆
ShanghaiCity浦东New区世纪大道
周小伟
26
1993-07-11
吃饭
ShenzhenCity南山区深南大道
张小发
33
1999-12-12
睡觉
NanjingCity龙眠大道
<template>
  <b-form ref="formRef" :model="list" label-width="85px" label-position="top">
    <b-collapse-wrap title="Edittable" shadow="none">
      <div style="padding: 10px 24px">
        <b-table
          edit-table
          :columns="columns"
          :data="list"
          no-data-text="暂无parameter"
          draggable
          drag-handle=".handle"
          max-height="420"
          @drag-drop="handleDragDrop"
        >
          <template #handle>
            <b-icon name="drag" class="handle" />
          </template>
          <template #name="{ index }">
            <b-form-item :rules="validateRules.name" :prop="index + '.name'">
              <b-input v-model="list[index].name" type="text" clearable></b-input>
            </b-form-item>
          </template>
          <template #age="{ index }">
            <b-form-item :rules="validateRules.age" :prop="index + '.age'">
              <b-input-number
                v-model="list[index].age"
                type="text"
                arrow-up-icon="plus"
                arrow-down-icon="minus"
              ></b-input-number>
            </b-form-item>
          </template>
          <template #birthday="{ index }">
            <b-form-item :rules="validateRules.birthday" :prop="index + '.birthday'">
              <b-date-picker
                v-model="list[index].birthday"
                type="date"
                placeholder="选择Day期"
              ></b-date-picker>
            </b-form-item>
          </template>
          <template #hobby="{ index }">
            <b-form-item :rules="validateRules.hobby" :prop="index + '.hobby'">
              <b-select v-model="list[index].hobby" clearable>
                <b-option v-for="(val, key) in hobbyMap" :key="key" :value="key" :label="val">
                  {{ val }}
                </b-option>
              </b-select>
            </b-form-item>
          </template>
          <template #address="{ index }">
            <b-form-item :rules="validateRules.address" :prop="index + '.address'">
              <b-input v-model="list[index].address" type="text"></b-input>
            </b-form-item>
          </template>
          <template #action="{ index }">
            <b-button type="text" text-color="danger" @click="handleRemove(index)">
              <b-icon name="minus-circle" />
            </b-button>
          </template>
        </b-table>
        <div class="mt-8">
          <b-button icon="plus" dashed style="width: 100%" @click="handleAdd">New增</b-button>
        </div>
      </div>
    </b-collapse-wrap>

    <b-collapse-wrap title="Readonly" shadow="none">
      <div style="padding: 10px 24px">
        <b-table :columns="columns2" :data="list" edit-table edit-table-detail>
          <template #hobby="{ row }">
            {{ hobbyMap[row.hobby] }}
          </template>
        </b-table>
      </div>
    </b-collapse-wrap>
  </b-form>
</template>

<script setup lang="ts">
import { reactive, ref, nextTick } from 'vue'

const formRef = ref(null)
const tableRef = ref(null)

const hobbyMap = { 1: '吃饭', 2: '睡觉', 3: '打豆豆' }
const columns = [
  { title: ' ', slot: 'handle', width: 24, align: 'center' },
  { title: 'Name', slot: 'name' },
  { title: 'Age', slot: 'age' },
  { title: 'Birthday', slot: 'birthday' },
  { title: 'Hobby', slot: 'hobby' },
  { title: 'Address', slot: 'address' },
  { title: ' ', slot: 'action', width: 50, align: 'center' }
]
const columns2 = [
  { title: 'Name', key: 'name' },
  { title: 'Age', key: 'age' },
  { title: 'Birthday', key: 'birthday' },
  { title: 'Hobby', slot: 'hobby' },
  { title: 'Address', key: 'address' }
]

const validateRules = reactive({
  name: [{ required: true, message: '必填项', trigger: 'blur' }],
  age: [{ required: true, message: '必填项', trigger: 'change' }],
  birthday: [{ required: true, message: '必填项', trigger: 'change' }],
  hobby: [{ required: true, message: '必填项', trigger: 'change' }],
  address: [{ required: true, message: '必填项', trigger: 'blur' }]
})

const list = ref([
  {
    name: '王小明',
    age: 18,
    birthday: '1990-04-22',
    hobby: '1',
    address: 'BeijingCity朝阳区芍药居'
  },
  {
    name: '张小刚',
    age: 25,
    birthday: '1990-11-11',
    hobby: '1',
    address: 'BeijingCity海淀区西二旗'
  },
  {
    name: '李小红',
    age: 30,
    birthday: '1985-02-05',
    hobby: '3',
    address: 'ShanghaiCity浦东New区世纪大道'
  },
  {
    name: '周小伟',
    age: 26,
    birthday: '1993-07-11',
    hobby: '1',
    address: 'ShenzhenCity南山区深南大道'
  },
  {
    name: '张小发',
    age: 33,
    birthday: '1999-12-12',
    hobby: '2',
    address: 'NanjingCity龙眠大道'
  }
])

function handleAdd() {
  const row = {
    name: '',
    age: null,
    birthday: '',
    hobby: '',
    address: ''
  }
  list.value.push(row)
}

function handleRemove(index) {
  list.value.splice(index, 1)
}

function handleDragDrop(newList, newIndex) {
  list.value = [...newList]
  nextTick(() => tableRef.value && tableRef.value.clickCurrentRow(newIndex))
}
</script>

Drag to Reorder

Set draggable to enable drag sorting.

Note: When drag sorting is enabled, mouse dragging also takes over text selection. You can set handle to limit dragging to a specific element.

To update the data order, use v-model:data for two-way binding, or handle the update manually in the @drag-drop event.

Default Drag

ID
Name
Age
Date of Birth
Address
1
John Brown
18
1990-04-22
New York No. 1 Lake Park
2
Jim Green
25
1990-11-11
London No. 1 Lake Park
3
Joe Black
30
1985-02-05
Sydney No. 1 Lake Park
4
Jon Snow
26
1993-07-11
Ottawa No. 2 Lake Park
5
Jim Raynor
33
1999-12-12
Moscow No. 3 Lake Park

Actual Data: [ "1-John Brown", "2-Jim Green", "3-Joe Black", "4-Jon Snow", "5-Jim Raynor" ]

When combined with single selection, it is recommended to use the drag-drop function for custom control, which better implements custom selection effects

Drag Handle

#
ID
Name
Age
Date of Birth
Address
Actions
1
John Brown
18
1990-04-22
New York No. 1 Lake Park
2
Jim Green
25
1990-11-11
London No. 1 Lake Park
3
Joe Black
30
1985-02-05
Sydney No. 1 Lake Park
4
Jon Snow
26
1993-07-11
Ottawa No. 2 Lake Park
5
Jim Raynor
33
1999-12-12
Moscow No. 3 Lake Park

Actual Data: [ "1-John Brown", "2-Jim Green", "3-Joe Black", "4-Jon Snow", "5-Jim Raynor" ]

Selected Row: {}

<template>
  <div>
    <div>
      <p>Default Drag</p>
      <b-table v-model:data="data1" :columns="columns1" draggable></b-table>
      <p>Actual Data: {{ data1.map(v => v.id + '-' + v.name) }}</p>
    </div>
    <b-divider></b-divider>
    <div>
      <p>When combined with single selection, it is recommended to use the drag-drop function for custom control, which better implements custom selection effects</p>
      <p>Drag Handle</p>
      <b-table
        ref="currentRowTable"
        :columns="columns2"
        :data="data2"
        draggable
        drag-handle=".drag-handle"
        highlight-row
        @drag-drop="handleDragDrop"
        @current-change="currentRowChange"
      >
        <template #handle="{ row }">
          <span class="drag-handle" style="cursor: grab"><b-icon name="drag" size="20" /></span>
        </template>
        <template #ctrl="{ row, index }">
          <b-button type="text" @click.stop="handleEdit(row, index)">Edit</b-button>
          <b-button type="text" text-color="danger" @click.stop="removeRow(index)">Delete</b-button>
        </template>
      </b-table>
      <p>Actual Data: {{ data2.map(v => v.id + '-' + v.name) }}</p>
      <p>Selected Row: {{ currentRow }}</p>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, nextTick } from 'vue'
const columns1 = [
  { title: 'ID', key: 'id', width: 70 },
  { title: 'Name', key: 'name' },
  { title: 'Age', key: 'age' },
  { title: 'Date of Birth', key: 'birthday' },
  { title: 'Address', key: 'address' }
]
const columns2 = [
  { slot: 'handle', width: 70 },
  { title: 'ID', key: 'id', width: 70 },
  { title: 'Name', key: 'name' },
  { title: 'Age', key: 'age' },
  { title: 'Date of Birth', key: 'birthday' },
  { title: 'Address', key: 'address' },
  { title: 'Actions', slot: 'ctrl', width: 120 }
]
const data1 = ref([
  {
    id: 1,
    name: 'John Brown',
    age: 18,
    birthday: '1990-04-22',
    address: 'New York No. 1 Lake Park'
  },
  {
    id: 2,
    name: 'Jim Green',
    age: 25,
    birthday: '1990-11-11',
    address: 'London No. 1 Lake Park'
  },
  {
    id: 3,
    name: 'Joe Black',
    age: 30,
    birthday: '1985-02-05',
    address: 'Sydney No. 1 Lake Park'
  },
  {
    id: 4,
    name: 'Jon Snow',
    age: 26,
    birthday: '1993-07-11',
    address: 'Ottawa No. 2 Lake Park'
  },
  {
    id: 5,
    name: 'Jim Raynor',
    age: 33,
    birthday: '1999-12-12',
    address: 'Moscow No. 3 Lake Park'
  }
])
const data2 = ref([
  {
    id: 1,
    name: 'John Brown',
    age: 18,
    birthday: '1990-04-22',
    address: 'New York No. 1 Lake Park'
  },
  {
    id: 2,
    name: 'Jim Green',
    age: 25,
    birthday: '1990-11-11',
    address: 'London No. 1 Lake Park'
  },
  {
    id: 3,
    name: 'Joe Black',
    age: 30,
    birthday: '1985-02-05',
    address: 'Sydney No. 1 Lake Park'
  },
  {
    id: 4,
    name: 'Jon Snow',
    age: 26,
    birthday: '1993-07-11',
    address: 'Ottawa No. 2 Lake Park'
  },
  {
    id: 5,
    name: 'Jim Raynor',
    age: 33,
    birthday: '1999-12-12',
    address: 'Moscow No. 3 Lake Park'
  }
])
const currentRow = ref({})
const currentRowTable = ref(null)

function currentRowChange(row, oldRow, index) {
  currentRow.value = row
}
function handleDragDrop(newList, newIndex, oldIndex) {
  data2.value = [...newList]
  nextTick(() => {
    currentRowTable.value.clickCurrentRow(newIndex)
  })
}
function handleEdit(row, index) {
  console.log(row, index)
}
function removeRow(index) {
  data2.value.splice(index, 1)
  nextTick(() => {
    currentRowTable.value.clearCurrentRow()
  })
}
</script>

Loading State

Name
Age
Birthday
Address
王小明
18
1990-04-22
BeijingCity朝阳区芍药居
张小刚
25
1990-11-11
BeijingCity海淀区西二旗
李小红
30
1985-02-05
ShanghaiCity浦东New区世纪大道
周小伟
26
1993-07-11
ShenzhenCity南山区深南大道
张小发
33
1999-12-12
NanjingCity龙眠大道

<template>
  <div>
    <b-table :columns="columns" :data="data" :loading="loading"></b-table>
    <br />
    <b-switch v-model="loading"></b-switch>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const columns = [
  { title: 'Name', key: 'name' },
  { title: 'Age', key: 'age' },
  { title: 'Birthday', key: 'birthday' },
  { title: 'Address', key: 'address' }
]
const data = ref([
  {
    name: '王小明',
    age: 18,
    birthday: '1990-04-22',
    address: 'BeijingCity朝阳区芍药居'
  },
  {
    name: '张小刚',
    age: 25,
    birthday: '1990-11-11',
    address: 'BeijingCity海淀区西二旗'
  },
  {
    name: '李小红',
    age: 30,
    birthday: '1985-02-05',
    address: 'ShanghaiCity浦东New区世纪大道'
  },
  {
    name: '周小伟',
    age: 26,
    birthday: '1993-07-11',
    address: 'ShenzhenCity南山区深南大道'
  },
  {
    name: '张小发',
    age: 33,
    birthday: '1999-12-12',
    address: 'NanjingCity龙眠大道'
  }
])
const loading = ref(false)
</script>

Sizes

Set size to large, default, or small to adjust the table size. The default row height is 40px, and small uses 36px. Leaving it unset is the same as default.

Name
Age
Date of Birth
Address
John Brown
18
1990-04-22
New York No. 1 Lake Park
Jim Green
25
1990-11-11
London No. 1 Lake Park
Joe Black
30
1985-02-05
Sydney No. 1 Lake Park
Jon Snow
26
1993-07-11
Ottawa No. 2 Lake Park
Jim Raynor
33
1999-12-12
Moscow No. 3 Lake Park
<template>
  <div>
    <div class="mb-16">
      <b-radio-group v-model="tableSize" type="button">
        <b-radio label="large">Loose</b-radio>
        <b-radio label="default">Default</b-radio>
        <b-radio label="small">Compact</b-radio>
      </b-radio-group>
    </div>
    <b-table :columns="columns" :data="data" :size="tableSize"></b-table>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const columns = [
  { title: 'Name', key: 'name' },
  { title: 'Age', key: 'age' },
  { title: 'Date of Birth', key: 'birthday' },
  { title: 'Address', key: 'address' }
]
const data = ref([
  {
    name: 'John Brown',
    age: 18,
    birthday: '1990-04-22',
    address: 'New York No. 1 Lake Park'
  },
  {
    name: 'Jim Green',
    age: 25,
    birthday: '1990-11-11',
    address: 'London No. 1 Lake Park'
  },
  {
    name: 'Joe Black',
    age: 30,
    birthday: '1985-02-05',
    address: 'Sydney No. 1 Lake Park'
  },
  {
    name: 'Jon Snow',
    age: 26,
    birthday: '1993-07-11',
    address: 'Ottawa No. 2 Lake Park'
  },
  {
    name: 'Jim Raynor',
    age: 33,
    birthday: '1999-12-12',
    address: 'Moscow No. 3 Lake Park'
  }
])
const tableSize = ref('default')
</script>

Empty Data

Set noDataText for the empty data state.

Name
Age
Birthday
Address

No Data

<template>
  <b-table :columns="columns" :data="data" no-data-text="No Data"></b-table>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const columns = [
  { title: 'Name', key: 'name' },
  { title: 'Age', key: 'age' },
  { title: 'Birthday', key: 'birthday' },
  { title: 'Address', key: 'address' }
]
const data = ref([])
</script>

Table props

ParameterDescriptionTypeOptionsDefault
dataStructured data to display. The field cellClassName is reserved for setting custom cell class names, so do not use it in your data. See examples for specific style usage.Array[]
columnsColumn configuration, see below for detailsArray[]
stripeShow stripe rows alternatelyBooleanfalse/truefalse
borderShow vertical borderBooleanfalse/truefalse
show-headerWhether to show the table headerBooleanfalse/truetrue
widthTable width in pxNumber/Stringauto
heightTable height in px. When set, the body scrolls through the built-in scrollbar and the header stays fixedNumber/String
max-heightMax table height in px. When exceeded, the body scrolls through the built-in scrollbar and the header stays fixedNumber/String
loadingTable loading stateBooleanfalse
disabled-hoverDisable hover highlightBooleanfalse
highlight-rowEnable row highlight / single-selection mode.Booleanfalse
highlight-row-cancelWhether single-selection highlight can be canceled. If true, clicking the selected row again will deselect itBooleanfalse
sizeTable sizeStringlarge / default / smalldefault
no-data-textEmpty state textStringNo Data
loading-textLoading textStringLoading
draggableEnable drag to reorder rows. To sync metadata, use v-model:data or handle the @drag-drop event to update dataBooleanfalse
drag-handleDrag handle iconString
tooltip-themeTooltip theme used when a column enables tooltipStringdark / light
row-keyWhether to force refresh using the built-in row-key; pass a business key field name in tree table modeBoolean/Stringfalse
expand-column-keyColumn key used to render the tree expand control. Tree mode starts only when this is set and row-key is a stringString''
default-expanded-row-keysDefault expanded row keys in tree table mode, used in uncontrolled modeArray[]
expanded-row-keysControlled expanded row keys in tree table mode, used with update:expandedRowKeysArray
indent-sizeIndent width for tree table rowsNumber16
merge-methodMerge method for row/column spanningFunctionfalse
edit-tableEnable edit-table stylingBooleanfalse/truefalse
edit-table-detailEnable a denser detail editing style on top of edit-tableBooleanfalse/truefalse

Table events

Event NameDescriptionReturn Value
current-changeEffective when highlight-row is enabled; triggers when the current row changescurrentRow, oldCurrentRow,index
selectEffective in multi-select mode; triggers when an item is selectedselected items, recently selected
select-cancelEffective in multi-select mode; triggers when an item is deselectedselected items, deselected
select-allTriggers when all items are selectedselected items
select-all-cancelTriggers when all items are deselectedselected items
selection-changeTriggers when the selection changesselected items
sort-changeEffective when sortable; triggers when sorting is clickedcolumn: current column data, key: sort indicator, order (asc or desc)
row-clickTriggers when a row is clickedCurrent row data, index
row-dblclickTriggers when a row is double-clickedCurrent row data, index
expandTriggers when an expandable row with type: 'expand' is expanded or collapsedrow: current row data, status: current state
update:expandedRowKeysTriggers when the controlled tree expansion keys update. Use @update:expanded-row-keys in templatesexpandedRowKeys
expand-changeTriggers when a tree row expand state changesrow, expanded, expandedRowKeys
drag-dropTriggers when drag sort is releasedThe two rows' data indices and updated data: newData, newIndex, oldIndex

Table slot

NameDescription
headerTable header
footerTable footer
loadingLoading content

Table methods

Method NameDescriptionParameter
clickCurrentRowSelect a row by indexindex
clearCurrentRowClear the highlighted row; only works when highlight-row is enabled
handleResizeRecalculate column widths, fixed panes, and scrollbar layout manually
getSelectionGet selected rows
selectAllSet all currently selectable rows to selected or deselectedstatus

column

ParameterDescriptionTypeOptionsDefault
typeColumn typeStringindex、selection、expand、html String-
titleColumn header textString-#
keyField name for column dataString--
widthColumn widthNumber--
minWidthMinimum column widthNumber--
maxWidthMaximum column widthNumber--
alignAlignmentStringright,centerleft
classNameCSS class name for the columnString--
fixedWhether the column is fixed to the left or rightStringleft,right-
ellipsisWhen enabled, text will not wrapBoolean-false
tooltipWhen enabled, text will not wrap and shows full content via Tooltip componentBoolean-false
slotRender the column with a named slot. Slot params are row, column, and indexString--
renderCustom render function for the column; the first parameter is h, the second is an object containing row, column, and indexFunction--
renderHeaderCustom header render function. Params: { column, index }Function--
indexMethodAvailable when type is index. Custom index method; the row parameter is the current row contentFunction--
sortableWhether the corresponding column can be sortedBoolean ,'custom'-false
sortMethodCustom sort method; three parameters: a, b, and typeFunction--
sortTypeSet initial sort order. Accepted values: asc, descString--
childrenChild column definitions for grouped headers; parent fixed is inherited by childrenArray--