Check all with list item, pagination in Vue.js

Frontend Apr 11, 2021

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

To support checking 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 the 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 checkboxes 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 the listingSelect mixin

Here an edge case was handled if the total items retrieved was smaller than the 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 the 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