Check all with list item, pagination in Vue.js

Frontend Apr 12, 2021

I have created a mixin before that support pagination, filtering and searching in Vue.js and it is well integrated with antd-vue's table and list.

To support check all items in a table and list, I created another mixin. Here is the demo

Demo

But first of all, I would like to introduce the listing mixin first.

The listing mixin contains the following data, including the api where the data comes from, columns used to render the table, data retrieved from the api,  and configs for pagination, sorting, filtering and searching.

    data () {
        return {
            api: null,
            columns: [],
            data: [],
            listing: {
                pagination: {
                    showSizeChanger: true
                },
                sorter: {},
                filters: {},
                keyword: ''
            },
            loading: true,
            autoload: true
        }
    },
Data in listing mixin

The data was then fetched and updated via the following function, passing the config written in listing to the api.

        fetchData () {
            this.loading = true
            this.api(this.listing).then(({data}) => {
                // update current page and loading status
                this.updateData(data)
                this.loading = false
            }).catch(e => {
                if (e.response.status === 404) {
                    this.loading = false
                }
            })
        },
        updateData (data) {
          const pagination = { ...this.listing.pagination }
          pagination.total = data.total
          this.data = data.data
          this.listing.pagination = pagination
        },
Key methods in listing mixin

Therefore, to implement the check all function, I created another mixin called listingSelect, which contains the following data:

  data () {
    return {
      selection: {
        selectedKeys: []
      },
      selectionConfig: {
        key: 'id',
        dataSource: 'data',
        pageSize: 10,
        totalItems: 10
      }
    }
  },
Data in listingSelect mixin

For checkbox in antd-vue, we got two additional properties called checked and indeterminate, which will be true if the items were partially selected.

    isIndeterminate () {
      return this.selection.selectedKeys.length > 0 && this.selection.selectedKeys.length < this.selectionConfig.pageSize && this.selection.selectedKeys.length !== this.selectionConfig.totalItems
    },
    isAllChecked () {
      return this.selection.selectedKeys.length === this.selectionConfig.pageSize || this.selection.selectedKeys.length === this.selectionConfig.totalItems
    }
Computed properties in listingSelect mixin

Here an edge case was handled if the total items retrieved was smaller than page size.

The following methods will handle the selection.

    $toggleCheckAll(e) {
      if (e.target.checked) {
        this.selection.selectedKeys = this[this.selectionConfig.dataSource].map(item => item[this.selectionConfig.key])
      } else {
        this.selection.selectedKeys = []
      }
    },
    _findIndex (key) {
      return item => item === key
    },
    $isChecked (key) {
      return this.selection.selectedKeys.findIndex(this._findIndex(key)) !== -1
    },
    $toggleCheck (key) {
      const index = this.selection.selectedKeys.findIndex(this._findIndex(key))
      if (index !== -1) {
        this.selection.selectedKeys.splice(index, 1)
      } else {
        this.selection.selectedKeys.push(key)
      }
    }
Methods for handling the selection

Below is the Vue template code for checkbox:

                <a-checkbox
                  style="margin-right: 10px"
                  :indeterminate="isIndeterminate"
                  :checked="isAllChecked"
                  @change="$toggleCheckAll"/>
                  <a-button v-show="isIndeterminate || isAllChecked" size="small">Mark as read</a-button>
                  <a-button type="danger" v-show="isIndeterminate || isAllChecked" size="small">Delete</a-button>
Check all
              <a-checkbox
                style="margin-right: 10px"
                @change="$toggleCheck(item.id)"
                :checked="$isChecked(item.id)"
              />
Check item

Tags

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.