Filter/Sort/Paginate Datasets – vue-dataset

The vue-dataset library provides a set of components that allows you to filter, sort, and paginate any data (like lists, cards, tables) in Vue applications.

Basic Usage:

1. Import components into your app.

import { 
  Dataset,
  DatasetItem,
  DatasetInfo,
  DatasetPager,
  DatasetSearch,
  DatasetShow
} from 'vue-dataset';

2. The example shows how to filter, sort, and paginate datasets in a card layout.

<template>
  <div>
    <h3>Custom filters</h3>
    <div class="row mb-1">
      <div class="col-md-6 mb-2 mb-md-0">
        <div class="btn-group">
          <button type="button" class="btn btn-outline-secondary" :class="[onlineFilter === '' && 'active']" @click.prevent="onlineFilter = ''">
            <span class="badge bg-white text-secondary">{{ users.length }}</span> All
          </button>
          <button type="button" class="btn btn-outline-secondary" :class="[onlineFilter === 'Active' && 'active']" @click.prevent="onlineFilter = 'Active'">
            <span class="badge bg-success text-white">{{ filterList(users, {'onlineStatus': 'Active'}).length }}</span> Active
          </button>
          <button type="button" class="btn btn-outline-secondary" :class="[onlineFilter === 'Away' && 'active']" @click.prevent="onlineFilter = 'Away'">
            <span class="badge bg-warning text-white">{{ filterList(users, {'onlineStatus': 'Away'}).length }}</span> Away
          </button>
          <button type="button" class="btn btn-outline-secondary" :class="[onlineFilter === 'Do not disturb' && 'active']" @click.prevent="onlineFilter = 'Do not disturb'">
            <span class="badge bg-danger text-white">{{ filterList(users, {'onlineStatus': 'Do not disturb'}).length }}</span> Do not disturb
          </button>
          <button type="button" class="btn btn-outline-secondary" :class="[onlineFilter === 'Invisible' && 'active']" @click.prevent="onlineFilter = 'Invisible'">
            <span class="badge bg-secondary text-white">{{ filterList(users, {'onlineStatus': 'Invisible'}).length }}</span> Invisible
          </button>
        </div>
      </div>
      <div class="col-md-6">
        <input type="text" class="form-control" placeholder="Name starts with" @input="startWithInput($event)">
      </div>
    </div>
    <hr class="mb-1" />
    <h3>Sorting</h3>
    <div class="row mb-2">
      <div class="col-md-6 mb-2 mb-md-0">
        <button type="button" class="btn btn-outline-secondary" @click="firstNameAsc = !firstNameAsc">First name {{ firstNameAsc ? 'asc' : 'desc' }}</button>
      </div>
    </div>
    <hr />
    <dataset
      v-slot="{ ds }"
      :ds-data="users"
      :ds-filter-fields="{ onlineStatus: onlineFilter, name: startsWithFilter }"
      :ds-sortby="[sortFirstName]"
      :ds-search-in="['balance', 'birthdate', 'name', 'company', 'email', 'phone', 'address', 'favoriteAnimal']"
      :ds-search-as="{ birthdate: searchAsEuroDate }"
    >
      <div class="row mb-2">
        <div class="col-md-6 mb-2 mb-md-0">
          <dataset-show />
        </div>
        <div class="col-md-6">
          <dataset-search ds-search-placeholder="Search..." :wait="300" />
        </div>
      </div>
      <div class="row">
        <div class="col-md-12">
          <dataset-item class="form-row mb-3" style="overflow-y: auto; max-height: 400px;">
            <template v-slot="{ row, rowIndex }">
              <div class="col-md-4">
                <div class="card mb-2">
                  <div class="card-body pt-3 pb-2 px-3">
                    <h5 class="card-title text-truncate mb-2" :title="`Index: ${ rowIndex }`">
                      <span :class="['font-16', statusClass[row.onlineStatus]]">⬤</span> {{ row.name }}
                    </h5>
                    <h6 class="card-subtitle text-truncate text-muted">{{ row.email }}</h6>
                    <p class="card-text text-truncate mb-0">{{ row.balance }}</p>
                    <p class="card-text text-truncate text-right">{{ isoDateToEuroDate(row.birthdate) }}</p>
                  </div>
                </div>
              </div>
            </template>
            <template v-slot:noDataFound>
              <div class="col-md-12 pt-2">
                <p class="text-center">No results found</p>
              </div>
            </template>
          </dataset-item>
        </div>
      </div>
      <div class="d-flex flex-md-row flex-column justify-content-between align-items-center">
        <dataset-info class="mb-2 mb-md-0" />
        <dataset-pager />
      </div>
    </dataset>
  </div>
</template>
export default {
  name: 'Example',
  data: function () {
    return {
      users: users,
      startsWith: '',
      onlineFilter: '',
      statusClass: {
        Active: 'text-success',
        Away: 'text-warning',
        'Do not disturb': 'text-danger',
        Invisible: 'text-secondary'
      },
      firstNameAsc: true
    };
  },
  computed: {
    sortFirstName () {
      return this.firstNameAsc ? 'firstName' : '-firstName';
    }
  },
  created () {
    this.startWithInput = debounce((e) => {
      this.startsWith = e.target.value;
    }, 300);
  },
  methods: {
    filterList,
    isoDateToEuroDate,
    searchAsEuroDate,
    updateData () {
      const updatedUsers = clone(users).slice(5, 10);
      this.users = updatedUsers;
    },
    startsWithFilter (value) {
      return value.toLowerCase().startsWith(this.startsWith.toLowerCase());
    }
  }
};

3. This example shows to how create a data table.

<template>
  <div>
    <dataset
      v-slot="{ ds }"
      :ds-data="users"
      :ds-sortby="sortBy"
      :ds-sort-as="{ birthdate: isoDateToDate }"
      :ds-search-in="['balance', 'birthdate', 'name', 'company', 'email', 'phone', 'address', 'favoriteAnimal']"
      :ds-search-as="{ birthdate: searchAsEuroDate }"
    >
      <div class="row">
        <div class="col-md-6 mb-2 mb-md-0">
          <dataset-show />
        </div>
        <div class="col-md-6">
          <dataset-search ds-search-placeholder="Search..." :wait="300" />
        </div>
      </div>
      <div class="row">
        <div class="col-md-12">
          <div class="table-responsive">
            <table class="table table-striped d-md-table">
              <thead>
                <tr>
                  <th scope="col">#</th>
                  <th v-for="(th, index) in cols" :key="th.field" :class="['sort', th.sort]" @click="click($event, index)">
                    {{ th.name }} <i class="gg-select float-right"></i>
                  </th>
                </tr>
              </thead>
              <dataset-item tag="tbody">
                <template v-slot="{ row, rowIndex }">
                  <tr>
                    <th scope="row">{{ rowIndex + 1 }}</th>
                    <td>{{ row.name }}</td>
                    <td>{{ row.email }}</td>
                    <td>{{ isoDateToEuroDate(row.birthdate) }}</td>
                  </tr>
                </template>
              </dataset-item>
            </table>
          </div>
        </div>
      </div>
      <div class="d-flex flex-md-row flex-column justify-content-between align-items-center">
        <dataset-info class="mb-2 mb-md-0" />
        <dataset-pager />
      </div>
    </dataset>
  </div>
</template>
export default {
  name: 'Example',
  data: function () {
    return {
      users: users,
      cols: [
        {
          name: 'Name',
          field: 'name',
          sort: ''
        },
        {
          name: 'Email',
          field: 'email',
          sort: ''
        },
        {
          name: 'Birthdate',
          field: 'birthdate',
          sort: ''
        }
      ]
    };
  },
  computed: {
    sortBy () {
      return this.cols.reduce((acc, o) => {
        if (o.sort) {
          o.sort === 'asc' ? acc.push(o.field) : acc.push('-' + o.field);
        }
        return acc;
      }, []);
    }
  },
  methods: {
    click (event, i) {
      let toset;
      const sortEl = this.cols[i];
      if (!event.shiftKey) {
        this.cols.forEach(o => {
          if (o.field !== sortEl.field) {
            o.sort = '';
          }
        });
      }
      if (!sortEl.sort) {
        toset = 'asc';
      }
      if (sortEl.sort === 'desc') {
        toset = event.shiftKey ? '' : 'asc';
      }
      if (sortEl.sort === 'asc') {
        toset = 'desc';
      }
      sortEl.sort = toset;
    },
    isoDateToEuroDate,
    isoDateToDate,
    searchAsEuroDate
  }
};

Preview:

filter-sort-paginate-datasets-vue-dataset

Changelog:

v1.1.18 (08/31/2023)

  • bugfixes

v1.1.17 (11/06/2022)

  • bugfixes

v1.1.16 (08/07/2022)

  • fixed set active page to last page

v1.1.15 (07/18/2022)

  • fixed table spacing

v1.1.14 (06/12/2022)

  • Bug Fixes

v1.1.13 (04/20/2022)

  • Bug Fixes

v1.1.12 (01/22/2022)

  • Bug Fixes

v1.1.10/11 (01/08/2022)

  • Bug Fixes

v1.1.9 (09/27/2021)

  • fix: added iteration index

v1.1.8 (09/19/2021)

  • Bug Fixes

v1.1.7 (08/09/2021)

  • Bug Fixes

v1.1.6 (08/05/2021)

  • Bug Fixes

v1.1.5 (07/24/2021)

  • Bug Fixes

v1.1.2 (05/07/2021)

  • Update

Download Details:

Author: kouts

Live Demo: https://vue-dataset-demo.netlify.app/examples/cards/

Download Link: https://github.com/kouts/vue-dataset/archive/refs/heads/master.zip

Official Website: https://github.com/kouts/vue-dataset

Install & Download:

# NPM
$ npm i vue-dataset

Add Comment