CoreUI for Vue.js logo
Angular JavaScript / Vanilla JS React.js
  • undefinedGetting started
  • undefinedCustomize
  • undefinedLayout
  • undefinedForms
  • undefinedComponents
  • undefinedTemplates
  • undefinedMigration
  • undefined
  • undefined
  • undefined
undefinedDownloadundefinedHire Us Get CoreUI PRO

CoreUI PRO Component

To use this component you must have a CoreUI PRO license. Buy the CoreUI PRO and get access to all PRO components, features, templates, and dedicated support.

Vue Smart Table Component (DataTable)

A Vue Smart Table provides a full set of features for displaying and manipulating tabular data. It allows you to easily create dynamic and interactive tables with features such as sorting, filtering, pagination, and searching. Vue Smart Table Component (DataTables) makes it easy to work with large datasets, and it is widely used in a variety of applications, including web-based applications, e-commerce sites, and more.

Other frameworks

CoreUI components are available as native Angular, Bootstrap (Vanilla JS), and React components. To learn more please visit the following pages.

  • Angular Smart Table
  • React Smart Table

Features #

  • Filter items by one or all columns
  • Sort items by column
  • Integrated with CPagination component by default
  • Customize style of specific rows, columns and cells
  • Customize display of columns
  • Load with initial filters and sorter state
  • Loading state visualization
  • Default header labels generation based on column names

Basic usage #

Name
Registered
Role
Status
Avram Tarasios2018/02/01StaffBanned

User since: 2018/02/01

Nehemiah Tatius2018/02/01StaffBanned

User since: 2018/02/01

Paĉjo Jadon2018/02/01StaffBanned

User since: 2018/02/01

Zbyněk Phoibos2018/02/01StaffBanned

User since: 2018/02/01

Ford Prefect2001/05/25AlienDon't panic!

User since: 2001/05/25

Name
Registered
Role
Status
  • «
  • ‹
  • 1
  • 2
  • 3
  • 4
  • 5
  • ›
  • »
<template>
  <CSmartTable
    clickableRows
    :tableProps="{
      striped: true,
      hover: true,
    }"
    :tableHeadProps="{
      color: 'danger',
    }"
    :activePage="1"
    footer
    header
    :items="items"
    :columns="columns"
    columnFilter
    tableFilter
    cleaner
    itemsPerPageSelect
    :itemsPerPage="5"
    columnSorter
    :sorterValue="{ column: 'status', state: 'asc' }"
    pagination
  >
    <template #status="{ item }">
      <td>
        <CBadge :color="getBadge(item.status)">{{ item.status }}</CBadge>
      </td>
    </template>
    <template #show_details="{ item, index }">
      <td class="py-2">
        <CButton
          color="primary"
          variant="outline"
          square
          size="sm"
          @click="toggleDetails(item, index)"
        >
          {{ Boolean(item._toggled) ? 'Hide' : 'Show' }}
        </CButton>
      </td>
    </template>
    <template #details="{ item }">
      <CCollapse :visible="this.details.includes(item._id)">
        <CCardBody>
          <h4>
            {{ item.username }}
          </h4>
          <p class="text-muted">User since: {{ item.registered }}</p>
          <CButton size="sm" color="info" class=""> User Settings </CButton>
          <CButton size="sm" color="danger" class="ml-1"> Delete </CButton>
        </CCardBody>
      </CCollapse>
    </template>
  </CSmartTable>
</template>
<script>
export default {
  data() {
    return {
      columns: [
        {
          key: 'name',
          _style: { width: '40%' },
          _props: { color: 'primary', class: 'fw-semibold' },
        },
        'registered',
        { key: 'role', filter: false, sorter: false, _style: { width: '20%' } },
        { key: 'status', _style: { width: '20%' } },
        {
          key: 'show_details',
          label: '',
          _style: { width: '1%' },
          filter: false,
          sorter: false,
          _props: { color: 'primary', class: 'fw-semibold' },
        },
      ],
      details: [],
      items: [
        { name: 'John Doe', registered: '2018/01/01', role: 'Guest', status: 'Pending' },
        {
          name: 'Samppa Nori',
          registered: '2018/01/01',
          role: 'Member',
          status: 'Active',
          _props: { color: 'primary', align: 'middle' },
        },
        {
          name: 'Estavan Lykos',
          registered: '2018/02/01',
          role: 'Staff',
          status: 'Banned',
          _cellProps: { all: { class: 'fw-semibold' }, name: { color: 'info' } },
        },
        { name: 'Chetan Mohamed', registered: '2018/02/01', role: 'Admin', status: 'Inactive' },
        { name: 'Derick Maximinus', registered: '2018/03/01', role: 'Member', status: 'Pending' },
        { name: 'Friderik Dávid', registered: '2018/01/21', role: 'Staff', status: 'Active' },
        { name: 'Yiorgos Avraamu', registered: '2018/01/01', role: 'Member', status: 'Active' },
        {
          name: 'Avram Tarasios',
          registered: '2018/02/01',
          role: 'Staff',
          status: 'Banned',
          _props: { color: 'warning', align: 'middle' },
        },
        { name: 'Quintin Ed', registered: '2018/02/01', role: 'Admin', status: 'Inactive' },
        { name: 'Enéas Kwadwo', registered: '2018/03/01', role: 'Member', status: 'Pending' },
        { name: 'Agapetus Tadeáš', registered: '2018/01/21', role: 'Staff', status: 'Active' },
        { name: 'Carwyn Fachtna', registered: '2018/01/01', role: 'Member', status: 'Active' },
        { name: 'Nehemiah Tatius', registered: '2018/02/01', role: 'Staff', status: 'Banned' },
        { name: 'Ebbe Gemariah', registered: '2018/02/01', role: 'Admin', status: 'Inactive' },
        { name: 'Eustorgios Amulius', registered: '2018/03/01', role: 'Member', status: 'Pending' },
        { name: 'Leopold Gáspár', registered: '2018/01/21', role: 'Staff', status: 'Active' },
        { name: 'Pompeius René', registered: '2018/01/01', role: 'Member', status: 'Active' },
        { name: 'Paĉjo Jadon', registered: '2018/02/01', role: 'Staff', status: 'Banned' },
        { name: 'Micheal Mercurius', registered: '2018/02/01', role: 'Admin', status: 'Inactive' },
        { name: 'Ganesha Dubhghall', registered: '2018/03/01', role: 'Member', status: 'Pending' },
        { name: 'Hiroto Šimun', registered: '2018/01/21', role: 'Staff', status: 'Active' },
        { name: 'Vishnu Serghei', registered: '2018/01/01', role: 'Member', status: 'Active' },
        { name: 'Zbyněk Phoibos', registered: '2018/02/01', role: 'Staff', status: 'Banned' },
        { name: 'Aulus Agmundr', registered: '2018/01/01', role: 'Member', status: 'Pending' },
        { name: 'Ford Prefect', registered: '2001/05/25', role: 'Alien', status: "Don't panic!" },
      ],
    }
  },
  methods: {
    getBadge(status) {
      switch (status) {
        case 'Active':
          return 'success'
        case 'Inactive':
          return 'secondary'
        case 'Pending':
          return 'warning'
        case 'Banned':
          return 'danger'
        default:
          'primary'
      }
    },
    toggleDetails(item) {
      if (this.details.includes(item._id)) {
        this.details = this.details.filter((_item) => _item !== item._id)
        return
      }
      this.details.push(item._id)
    },
  },
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

Default header labels generation based on column names #

By default, Vue Table component will generate the header labels for each column based on the column's data source.

Name
Registered
Role
Status
John Doe2018/01/01GuestPending
Samppa Nori2018/01/01MemberActive
Estavan Lykos2018/02/01StaffBanned
Chetan Mohamed2018/02/01AdminInactive
Derick Maximinus2018/03/01MemberPending
Friderik Dávid2018/01/21StaffActive
Yiorgos Avraamu2018/01/01MemberActive
Avram Tarasios2018/02/01StaffBanned
Quintin Ed2018/02/01AdminInactive
Enéas Kwadwo2018/03/01MemberPending
  • «
  • ‹
  • 1
  • 2
  • 3
  • ›
  • »

<template>
  <CSmartTable
    :items="items"
    columnFilter
    columnSorter
    pagination
    :tableProps="{
      hover: true,
    }"
  />
</template>
<script>
export default {
  data() {
    return {
      items: [
        { name: 'John Doe', registered: '2018/01/01', role: 'Guest', status: 'Pending' },
        {
          name: 'Samppa Nori',
          registered: '2018/01/01',
          role: 'Member',
          status: 'Active',
          _props: { color: 'primary', align: 'middle' },
        },
        {
          name: 'Estavan Lykos',
          registered: '2018/02/01',
          role: 'Staff',
          status: 'Banned',
          _cellProps: { all: { class: 'fw-semibold' }, name: { color: 'info' } },
        },
        { name: 'Chetan Mohamed', registered: '2018/02/01', role: 'Admin', status: 'Inactive' },
        { name: 'Derick Maximinus', registered: '2018/03/01', role: 'Member', status: 'Pending' },
        { name: 'Friderik Dávid', registered: '2018/01/21', role: 'Staff', status: 'Active' },
        { name: 'Yiorgos Avraamu', registered: '2018/01/01', role: 'Member', status: 'Active' },
        {
          name: 'Avram Tarasios',
          registered: '2018/02/01',
          role: 'Staff',
          status: 'Banned',
          _props: { color: 'warning', align: 'middle' },
        },
        { name: 'Quintin Ed', registered: '2018/02/01', role: 'Admin', status: 'Inactive' },
        { name: 'Enéas Kwadwo', registered: '2018/03/01', role: 'Member', status: 'Pending' },
        { name: 'Agapetus Tadeáš', registered: '2018/01/21', role: 'Staff', status: 'Active' },
        { name: 'Carwyn Fachtna', registered: '2018/01/01', role: 'Member', status: 'Active' },
        { name: 'Nehemiah Tatius', registered: '2018/02/01', role: 'Staff', status: 'Banned' },
        { name: 'Ebbe Gemariah', registered: '2018/02/01', role: 'Admin', status: 'Inactive' },
        { name: 'Eustorgios Amulius', registered: '2018/03/01', role: 'Member', status: 'Pending' },
        { name: 'Leopold Gáspár', registered: '2018/01/21', role: 'Staff', status: 'Active' },
        { name: 'Pompeius René', registered: '2018/01/01', role: 'Member', status: 'Active' },
        { name: 'Paĉjo Jadon', registered: '2018/02/01', role: 'Staff', status: 'Banned' },
        { name: 'Micheal Mercurius', registered: '2018/02/01', role: 'Admin', status: 'Inactive' },
        { name: 'Ganesha Dubhghall', registered: '2018/03/01', role: 'Member', status: 'Pending' },
        { name: 'Hiroto Šimun', registered: '2018/01/21', role: 'Staff', status: 'Active' },
        { name: 'Vishnu Serghei', registered: '2018/01/01', role: 'Member', status: 'Active' },
        { name: 'Zbyněk Phoibos', registered: '2018/02/01', role: 'Staff', status: 'Banned' },
        { name: 'Aulus Agmundr', registered: '2018/01/01', role: 'Member', status: 'Pending' },
        { name: 'Ford Prefect', registered: '2001/05/25', role: 'Alien', status: "Don't panic!" },
      ],
    }
  },
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

Custom filters #

CoreUI Vue Smart Table (Vue DataTables) provides a number of built-in features for filtering, searching, and sorting data, including the ability to use custom filtering functions.

To use a custom filter in Vue Smart Table (DataTables), you can use the filter option to specify a custom filter for each column.

Date Range Picker #

Here is an example of how you might use the <CDateRangePicker /> component to apply custom filters to a Vue DataTable component:

Name
Registered
Mo
Tu
We
Th
Fr
Sa
Su
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
Mo
Tu
We
Th
Fr
Sa
Su
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1
2
3
4
5
6
7
8
9
10
11
12
13
Estavan Lykos2/7/2022
Chetan Mohamed2/7/2022
Avram Tarasios2/7/2022
Quintin Ed2/7/2022
Nehemiah Tatius2/7/2022
Ebbe Gemariah2/7/2022
Paĉjo Jadon2/7/2022
Micheal Mercurius2/7/2022
Zbyněk Phoibos2/7/2022
Name
Registered
<template>
  <CSmartTable 
    cleaner
    clickableRows
    :columns="columnsDateRangePicker"
    columnFilter
    :columnFilterValue="{
      registered: 
        (date) => new Date(Date.parse(date)) >= startDate && new Date(Date.parse(date)) <= endDate
    }"
    columnSorter
    footer
    :items="itemsDateRangePicker"
    itemsPerPageSelect
    :itemsPerPage="10"
    pagination
    tableFilter
  >
    <template #registered="{ item }">
      <td>{{ convertToDate(item.registered) }}</td>
    </template>
  </CSmartTable>    
</template>
<script>
  import { h } from 'vue'
  import { CDateRangePicker } from '@coreui/vue-pro'
  export default {
    data() {
      return {
        startDate: new Date('2022-01-21'),
        endDate: new Date('2022-02-07'),
        columnsDateRangePicker: [
          {
            key: 'name',
            _style: { width: '50%' },
          },
          {
            key: 'registered',
            _style: { width: '50%' },
            filter: (values, onChange) => {
              const unique = [...new Set(values)].sort()
              return h(CDateRangePicker, {
                size: 'sm',
                startDate: this.startDate,
                endDate: this.endDate,
                minDate: this.minDate,
                maxDate: this.maxDate,
                onStartDateChange: (date) => {
                  this.setStartDate(date)
                  onChange((item) => {
                    if (date) {
                      const itemDate = new Date(Date.parse(item))
                      return this.endDate ? itemDate >= date && itemDate <= this.endDate : itemDate >= date
                    } 
                    return true
                  })
                },
                onEndDateChange: (date) => {
                  this.setEndDate(date)
                  onChange((item) => {
                    if (date) {
                      const itemDate = new Date(Date.parse(item))
                      return this.startDate ? itemDate <= date && itemDate >= this.startDate : itemDate <= date
                    } 
                    return true
                  })
                }
              })
            },
          }
        ],
        itemsDateRangePicker: [
          { id: 0, name: 'John Doe', registered: '2022/01/01' },
          {
            id: 1,
            name: 'Samppa Nori',
            registered: '2022/01/01',
          },
          {
            id: 2,
            name: 'Estavan Lykos',
            registered: '2022/02/07',
          },
          { id: 3, name: 'Chetan Mohamed', registered: '2022/02/07' },
          {
            id: 4,
            name: 'Derick Maximinus',
            registered: '2022/03/19',
          },
          { id: 5, name: 'Friderik Dávid', registered: '2022/01/21' },
          { id: 6, name: 'Yiorgos Avraamu', registered: '2022/01/01' },
          {
            id: 7,
            name: 'Avram Tarasios',
            registered: '2022/02/07',
          },
          { id: 8, name: 'Quintin Ed', registered: '2022/02/07' },
          { id: 9, name: 'Enéas Kwadwo', registered: '2022/02/19', role: 'Member', status: 'Pending' },
          { id: 10, name: 'Agapetus Tadeáš', registered: '2022/01/21' },
          { id: 11, name: 'Carwyn Fachtna', registered: '2022/01/01' },
          { id: 12, name: 'Nehemiah Tatius', registered: '2022/02/07' },
          { id: 13, name: 'Ebbe Gemariah', registered: '2022/02/07' },
          {
            id: 14,
            name: 'Eustorgios Amulius',
            registered: '2022/02/19',
          },
          { id: 15, name: 'Leopold Gáspár', registered: '2022/01/21' },
          { id: 16, name: 'Pompeius René', registered: '2022/01/01' },
          { id: 17, name: 'Paĉjo Jadon', registered: '2022/02/07' },
          {
            id: 18,
            name: 'Micheal Mercurius',
            registered: '2022/02/07',
          },
          {
            id: 19,
            name: 'Ganesha Dubhghall',
            registered: '2022/01/19',
          },
          { id: 20, name: 'Hiroto Šimun', registered: '2022/01/21' },
          { id: 21, name: 'Vishnu Serghei', registered: '2022/01/01' },
          { id: 22, name: 'Zbyněk Phoibos', registered: '2022/02/07' },
          {
            id: 23,
            name: 'Aulus Agmundr',
            registered: '2022/01/01',
          },
          {
            id: 42,
            name: 'Ford Prefect',
            registered: '2022/02/25',
          },
        ],
      }
    },
    computed: {
      minDate: function () {
        return new Date(
          Math.min(
            ...this.itemsDateRangePicker.map((item) => {
              return new Date(Date.parse(item.registered))
            }),
          ),
        )
      },
      maxDate: function () {
        return new Date(
          Math.max(
            ...this.itemsDateRangePicker.map((item) => {
              return new Date(Date.parse(item.registered))
            }),
          ),
        )
      }
    },
    methods: {
      convertToDate (date) {
        const _date = new Date(Date.parse(date))
        return _date.toLocaleDateString()
      },
      setStartDate (date) {
        this.startDate = date
      },
      setEndDate (date) {
        this.endDate = date
      }
    }
  }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

Multi Select #

Here is an example of how you might use the <CMultiSelect /> component to apply custom filters to a Vue DataTable:

Name
Role
Admin
Alien
Guest
Member
Staff
John DoeGuest
Samppa NoriMember
Estavan LykosStaff
Chetan MohamedAdmin
Derick MaximinusMember
Friderik DávidStaff
Yiorgos AvraamuMember
Avram TarasiosStaff
Quintin EdAdmin
Enéas KwadwoMember
Name
Role
  • «
  • ‹
  • 1
  • 2
  • 3
  • ›
  • »

<template>
  <CSmartTable
    cleaner
    clickableRows
    :columns="columnsMultiSelect"
    columnFilter
    columnSorter
    footer
    :items="itemsMultiSelect"
    itemsPerPageSelect
    :itemsPerPage="10"
    pagination
    tableFilter
  />
</template>
<script>
  import { h } from 'vue'
  import { CMultiSelect } from '@coreui/vue-pro'
  export default {
    data() {
      return {
        columnsMultiSelect: [
          {
            key: 'name',
            _style: { width: '50%' },
          },
          {
            key: 'role',
            _style: { width: '50%' },
            filter: (values, onChange) => {
              const unique = [...new Set(values)].sort()
              return h(CMultiSelect, {
                size: 'sm',
                onChange: (selected) => {
                  const _selected = selected.map((element) => element.value)
                  onChange(function(item) {
                    return Array.isArray(_selected) && _selected.length
                      ? _selected.includes(item.toLowerCase())
                      : true
                  })
                },
                options: unique.map((element) => {
                  return {
                    value: element.toLowerCase(),
                    text: element,
                  }
                })})
            },
            sorter: false,
          },
        ],
        itemsMultiSelect: [
          { id: 0, name: 'John Doe', role: 'Guest' },
          {
            id: 1,
            name: 'Samppa Nori',
            role: 'Member',
          },
          {
            id: 2,
            name: 'Estavan Lykos',
            role: 'Staff',
          },
          { id: 3, name: 'Chetan Mohamed', role: 'Admin' },
          {
            id: 4,
            name: 'Derick Maximinus',
            role: 'Member',
          },
          { id: 5, name: 'Friderik Dávid', role: 'Staff' },
          { id: 6, name: 'Yiorgos Avraamu', role: 'Member' },
          {
            id: 7,
            name: 'Avram Tarasios',
            role: 'Staff',
          },
          { id: 8, name: 'Quintin Ed', role: 'Admin' },
          { id: 9, name: 'Enéas Kwadwo', role: 'Member' },
          { id: 10, name: 'Agapetus Tadeáš', role: 'Staff' },
          { id: 11, name: 'Carwyn Fachtna', role: 'Member' },
          { id: 12, name: 'Nehemiah Tatius', role: 'Staff' },
          { id: 13, name: 'Ebbe Gemariah', role: 'Admin' },
          {
            id: 14,
            name: 'Eustorgios Amulius',
            role: 'Member',
          },
          { id: 15, name: 'Leopold Gáspár', role: 'Staff' },
          { id: 16, name: 'Pompeius René', role: 'Member' },
          { id: 17, name: 'Paĉjo Jadon', role: 'Staff' },
          {
            id: 18,
            name: 'Micheal Mercurius',
            role: 'Admin',
          },
          {
            id: 19,
            name: 'Ganesha Dubhghall',
            role: 'Member',
          },
          { id: 20, name: 'Hiroto Šimun', role: 'Staff' },
          { id: 21, name: 'Vishnu Serghei', role: 'Member' },
          { id: 22, name: 'Zbyněk Phoibos', role: 'Staff' },
          {
            id: 23,
            name: 'Aulus Agmundr',
            role: 'Member',
          },
          {
            id: 42,
            name: 'Ford Prefect',
            role: 'Alien',
          },
        ]
      }
    }
  }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

Data sources #

You can use Fetch API to load data from different sources and then pass them to <CSmartTable>

External Data (10.000+ records) #

One of the key features of Vue Smart Table (Vue DataTables) is the ability to load data from an external source, such as an API or a server-side script. This can be useful if you have a large amount of data that you don't want to load all at once, or if you want to allow users to interact with the data without having to reload the page.

To load external data into a Vue Smart Table (Vue DataTables), you can use the Fetch API to the data source.

Here is an example of how you might use Vue Smart Table with external data:

First Name
Last Name
Email
Country
IP
  • «
  • ‹
  • 1
  • ›
  • »

<template>
  <CSmartTable
    :columns="columnsExternalDataExample"
    :columnFilter="{
      external: true,
    }"
    :columnSorter="{
      external: true,
    }"
    :items="users"
    :itemsPerPage="itemsPerPage"
    itemsPerPageSelect
    :loading="loading"
    :pagination="{
      external: true,
    }"
    :paginationProps="{
      activePage: activePage,
      pages: Math.ceil(records / itemsPerPage) || 1,
    }"
    :tableProps="{
      hover: true,
      responsive: true,
    }"
    @active-Page-change="(activePage) => setActivePage(activePage)"
    @column-filter-change="(filter) => {
      setActivePage(1)
      setColumnFilter(filter)
    }"
    @items-per-page-change="(itemsPerPage) => {
      setActivePage(1)
      setItemsPerPage(itemsPerPage)
    }"
    @sorter-change="(sorter) => setColumnSorter(sorter)"
  />
</template>
<script>
  export default {
    data() {
      return {
        items: []
        activePage: 3,
        columnFilter: [],
        columnSorter: null,
        itemsPerPage: 10,
        users: [],
        records: [],
        columnsExternalDataExample: [
          {
            key: 'first_name',
            _style: { minWidth: '130px' },
          },
          {
            key: 'last_name',
            _style: { minWidth: '130px' },
          },
          'email',
          {
            key: 'country',
            _style: { minWidth: '120px' },
          },
          {
            key: 'ip_address',
            label: 'IP',
          },
        ]
      }
    },
    methods: {
      async getUsers () {
        const offset = this.itemsPerPage * this.activePage - this.itemsPerPage
        let params = new URLSearchParams()
        Object.keys(this.columnFilter).forEach((key) => {
          params.append(key, this.columnFilter[key])
        })
        this.columnSorter &&
          this.columnSorter.column !== undefined &&
          params.append('sort', `${this.columnSorter.column}%${this.columnSorter.state}`)
        this.setLoading(true)
        fetch(`https://apitest.coreui.io/demos/users?offset=${offset}&limit=${this.itemsPerPage}&${params}`)
          .then((response) => response.json())
          .then((result) => {
            this.setRecords(result.number_of_matching_records)
            result.number_of_matching_records ? this.setUsers(result.records) : this.setUsers([])
            this.setLoading(false)
          })
      },
      setActivePage (activePage) {
        this.activePage = activePage
      },
      setColumnFilter (columnFilter) {
        this.columnFilter = columnFilter
      },
      setColumnSorter (columnSorter) {
        this.columnSorter = columnSorter
      },
      setItemsPerPage (itemsPerPage) {
        this.itemsPerPage = itemsPerPage
      },
      setLoading (loading) {
        this.loading = loading
      },
      setRecords (records) {
        this.records = records
      },
      setUsers (users) {
        this.users = users
      }
    },
    watch: {
      activePage() {
        this.getUsers()
      },
      columnFilter() {
        this.getUsers()
      },
      columnSorter: {
        handler() {
          this.getUsers()
        },
        deep: true
      },
      itemsPerPage() {
        this.getUsers()
      }
    }, 
    mounted() {
      this.getUsers()
    }
  }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131

JSON (10.000+ records) #

The Fetch API can be used to load JSON data by making a GET request to the endpoint where the data is located. In this example, the fetch() method is used to make a GET request to the endpoint https://apitest.coreui.io/fake_data/users.json, which returns a response. The response.json() method is then used to parse the response as a JSON object. The resulting JSON object is stored in the users and loaded by <CSmartTable />.

First Name
Last Name
Email
Country
IP

<template>
  <CSmartTable
    :columns="columnsJSONDataExample"
    columnFilter
    columnSorter
    :items="usersJSON"
    itemsPerPageSelect
    :loading="loadingJSON"
    pagination
    :tableProps="{
      hover: true,
      responsive: true,
    }"
  />
</template>
<script>
  export default {
    data() {
      return {
        loadingJSON: false,
        usersJSON: [],
        columnsJSONDataExample: [
          {
            key: 'first_name',
            _style: { minWidth: '130px' },
          },
          {
            key: 'last_name',
            _style: { minWidth: '130px' },
          },
          'email',
          {
            key: 'country',
            _style: { minWidth: '120px' },
          },
          {
            key: 'ip_address',
            label: 'IP',
          },
        ]
      }
    },
    methods: {
      async getUsersJSON () {
        this.setLoadingJSON(true)
        fetch('https://apitest.coreui.io/fake_data/users.json')
          .then((response) => response.json())
          .then((result) => {
            this.setUsersJSON(result)
            this.setLoadingJSON(false)
          })
      },
      setLoadingJSON (loading) {
        this.loadingJSON = loading
      },
      setUsersJSON (users) {
        this.usersJSON = users
      }
    },
    mounted() {
      this.getUsersJSON()
    }
  }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

API #

CSmartTable #

import { CSmartTable } from '@coreui/vue-pro'
// or
import CSmartTable from '@coreui/vue-pro/src/components/smart-table/CSmartTable'
1
2
3

Props #

Prop nameDescriptionTypeValuesDefault
active-pageSets active page. If 'pagination' prop is enabled, activePage is set only initially.number-1
cleanerWhen set, displays table cleaner above table, next to the table filter (or in place of table filter if tableFilter prop is not set)
Cleaner resets tableFilterValue, columnFilterValue, sorterValue. If clean is possible it is clickable (tabIndex="0" role="button", color="danger"), otherwise it is not clickable and transparent. Cleaner can be customized through the cleanerIcon slot.
boolean-
clickable-rowsStyle table items as clickable.boolean-
column-filterWhen set, displays additional filter row between table header and items, allowing filtering by specific column.
Column filter can be customized, by passing prop as object with additional options as keys. Available options:
- external (Boolean) - Disables automatic filtering inside component.
- lazy (Boolean) - Set to true to trigger filter updates only on change event.
boolean | ColumnFilter-
column-filter-valueValue of table filter. To set pass object where keys are column names and values are filter strings e.g.:
{ user: 'John', age: 12 }
ColumnFilterValue--
columnsProp for table columns configuration. If prop is not defined, table will display columns based on the first item keys, omitting keys that begins with underscore (e.g. '_props')

In columns prop each array item represents one column. Item might be specified in two ways:
String: each item define column name equal to item value.
Object: item is object with following keys available as column configuration:
- key (required)(String) - define column name equal to item key.
- filter (Boolean) - removes filter from column when set to false.
- label (String) - define visible label of column. If not defined, label will be generated automatically based on column name, by converting kebab-case and snake_case to individual words and capitalization of each word.
- sorter (Boolean) - disables sorting of the column when set to false
- _props (String/Array/Object) - add props to CTableHeaderCell.
- _style (String/Array/Object) - adds styles to the column header (useful for defining widths)
Column[] | string[]-
column-sorterEnables table sorting by column value. Sorting will be performed corectly only if values in column are of one type: string (case insensitive) or number.

Sorter can be customized, by passing prop as object with additional options as keys. Available options:
- external (Boolean) - Disables automatic sorting inside component.
- resetable (Boolean) - If set to true clicking on sorter have three states: ascending, descending and null. That means that third click on sorter will reset sorting, and restore table to original order.
boolean | Sorter--
footerDisplays table footer, which mirrors table header. (without column filter).boolean-
headerSet to false to remove table header.boolean-true
itemsArray of objects, where each object represents one item - row in table. Additionally, you can customize each row by passing them by _props key and single cell by _cellProps.

Examples:
- _props: { color: 'primary', align: 'middle'}
- _cellProps: { all: { class: 'fw-semibold'}, 'name': { color: 'info' }}
Item[]-() => []
items-per-pageNumber of items per site, when pagination is enabled.number-10
items-per-page-labelLabel for items per page selector.string-'Items per page:'
items-per-page-optionsItems per page selector options.number[]-() => [5, 10, 20, 50]
items-per-page-selectAdds select element over table, which is used for control items per page in pagination. If you want to customize this element, pass object with optional values:
- label (String) - replaces default label text
- values (Array) - custom array of pagination values
- external (Boolean) - disables automatic 'itemsPerPage' change (use to change pages externaly by 'pagination-change' event).
boolean | ItemsPerPageSelect--
loadingWhen set, table will have loading style: loading spinner and reduced opacity. When 'small' prop is enabled spinner will be also smaller.boolean-
no-items-labelReactNode or string for passing custom noItemsLabel texts.string-'No items found'
paginationEnables default pagination. Set to true for default setup or pass an object with additional CPagination props. Default pagination will always have the computed number of pages that cannot be changed. The number of pages is generated based on the number of passed items and 'itemsPerPage' prop. If this restriction is an obstacle, you can make external CPagination instead.boolean | Pagination-
pagination-propsProperties to CSmartPagination component.object--
selectableAdd checkboxes to make table rows selectable.boolean-
sorter-valueState of the sorter. Name key is column name, direction can be 'asc' or 'desc'. eg.:
{ column: 'status', state: 'asc' }
SorterValue--
table-body-propsProperties to CTableBody component.object--
table-foot-propsProperties to CTableFoot component.object--
table-filterWhen set, displays table filter above table, allowing filtering by specific column.

Column filter can be customized, by passing prop as object with additional options as keys. Available options:
- external (Boolean) - Disables automatic filtering inside component.
- lazy (Boolean) - Set to true to trigger filter updates only on change event.
boolean | TableFilter-
table-filter-labelThe element represents a caption for a component.string-'Filter:'
table-filter-placeholderSpecifies a short hint that is visible in the search input.string-'type string...'
table-filter-valueValue of table filter.string--
table-head-propsProperties to CTableHead component.object--
table-propsProperties to CTable component.object--

Events #

Event nameDescriptionProperties
active-page-changePage change callback.page number - active page number
column-filter-changeColumn filter change callback.ColumnFilterValue object - {[key: string]: string | number}
filtered-items-changeFiltered items change callback.items array - undefined
items-per-page-changePagination change callback.itemsPerPageNumber number - items per page number
row-clickRow click callback.item object - undefined
index number - undefined
columnName string - undefined
event event - undefined
selected-items-changeSelected items change callback.items array - undefined
sorter-changeSorter value change callback.SorterValue object - { column?: string, state?: number | string}
table-filter-changeTable filter change callback.tableFilterValue string - undefined
On this page
  • Features
  • Basic usage
  • Default header labels generation based on column names
  • Custom filters
    • Date Range Picker
    • Multi Select
  • Data sources
    • External Data (10.000+ records)
    • JSON (10.000+ records)
  • API
    • CSmartTable
  • GitHub
  • Twitter
  • CoreUI (Vanilla)
  • CoreUI for Angular
  • CoreUI for React.js

CoreUI for Vue is Open Source UI Components Library for Vue.js.

CoreUI code licensed MIT, docs CC BY 3.0. CoreUI PRO requires a commercial license.