samargy_
samargy_

Reputation: 33

How to filter a bootstrap vue table with an input field

The title says it all. I want to filter my bootstrap table with an input box.

Here is my .html part of the component:

<b-table
:items="Table"
:fields="fields"
striped
small
>

</b-table>

Here is the .vue file

<template src="./jointable.component.html"> </template>
<style scoped src="./jointable.component.css"> </style>


<script>

import axios from 'axios'

export default {
    name: 'jointable',
    data(){
        return {
            Table: [],
            fields: [
                {key: 'client_id', label: "School Code", sortable: true},
                {key: 'client_name', sortable: true},
                {key: 'uuid', label: "ID", sortable: true},
                {key: 'step', label: "Job Running", sortable: true},
                {key: 'serverid', sortable: true},
                {key: 'create_timestamp', label: "Job Start", sortable: true},
                {key: 'time_elapsed', sortable: true},
                {key: 'wh_db_host', sortable: true}
            ]
        }
    },
    methods : {
        loadData: function(){
            axios.get("http://192.168.56.101:5000/jointable")
            .then((res) => {
                this.Table = res.data
            })
            .catch((err) => {
                console.log(err)
            })
        }
    },
    mounted() {
        this.loadData();

        setInterval(function(){
            this.loadData()
        }.bind(this), 10000)
    },
    computed() {

    }
}
</script>

So right now you can see that my script reloads the table every 10 seconds with updated data. This is fine. I want to also now have my table searchable/filterable. I know I have to use the computed thing but how do I use it.

Thank you to whoever helps me!

Upvotes: 1

Views: 8920

Answers (3)

mepsd
mepsd

Reputation: 39

Detailed Code for filtering bootstrap-vue please refer documentation Thanks

new Vue({
  el: '#app',
  data() {
    return {
      items: [{
          isActive: true,
          age: 40,
          name: {
            first: 'Dickerson',
            last: 'Macdonald'
          }
        },
        {
          isActive: false,
          age: 21,
          name: {
            first: 'Larsen',
            last: 'Shaw'
          }
        },
        {
          isActive: false,
          age: 9,
          name: {
            first: 'Mini',
            last: 'Navarro'
          },
          _rowVariant: 'success'
        },
        {
          isActive: false,
          age: 89,
          name: {
            first: 'Geneva',
            last: 'Wilson'
          }
        },
        {
          isActive: true,
          age: 38,
          name: {
            first: 'Jami',
            last: 'Carney'
          }
        },
        {
          isActive: false,
          age: 27,
          name: {
            first: 'Essie',
            last: 'Dunlap'
          }
        },
        {
          isActive: true,
          age: 40,
          name: {
            first: 'Thor',
            last: 'Macdonald'
          }
        },
        {
          isActive: true,
          age: 87,
          name: {
            first: 'Larsen',
            last: 'Shaw'
          },
          _cellVariants: {
            age: 'danger',
            isActive: 'warning'
          }
        },
        {
          isActive: false,
          age: 26,
          name: {
            first: 'Mitzi',
            last: 'Navarro'
          }
        },
        {
          isActive: false,
          age: 22,
          name: {
            first: 'Genevieve',
            last: 'Wilson'
          }
        },
        {
          isActive: true,
          age: 38,
          name: {
            first: 'John',
            last: 'Carney'
          }
        },
        {
          isActive: false,
          age: 29,
          name: {
            first: 'Dick',
            last: 'Dunlap'
          }
        }
      ],
      fields: [{
          key: 'name',
          label: 'Person full name',
          sortable: true,
          sortDirection: 'desc'
        },
        {
          key: 'age',
          label: 'Person age',
          sortable: true,
          class: 'text-center'
        },
        {
          key: 'isActive',
          label: 'Is Active',
          formatter: (value, key, item) => {
            return value ? 'Yes' : 'No'
          },
          sortable: true,
          sortByFormatted: true,
          filterByFormatted: true
        },
        {
          key: 'actions',
          label: 'Actions'
        }
      ],
      totalRows: 1,
      currentPage: 1,
      perPage: 5,
      pageOptions: [5, 10, 15, {
        value: 100,
        text: "Show a lot"
      }],
      sortBy: '',
      sortDesc: false,
      sortDirection: 'asc',
      filter: null,
      filterOn: [],
      infoModal: {
        id: 'info-modal',
        title: '',
        content: ''
      }
    }
  },
  computed: {
    sortOptions() {
      // Create an options list from our fields
      return this.fields
        .filter(f => f.sortable)
        .map(f => {
          return {
            text: f.label,
            value: f.key
          }
        })
    }
  },
  mounted() {
    // Set the initial number of items
    this.totalRows = this.items.length
  },
  methods: {
    info(item, index, button) {
      this.infoModal.title = `Row index: ${index}`
      this.infoModal.content = JSON.stringify(item, null, 2)
      this.$root.$emit('bv::show::modal', this.infoModal.id, button)
    },
    resetInfoModal() {
      this.infoModal.title = ''
      this.infoModal.content = ''
    },
    onFiltered(filteredItems) {
      // Trigger pagination to update the number of buttons/pages due to filtering
      this.totalRows = filteredItems.length
      this.currentPage = 1
    }
  }

})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/[email protected]/dist/bootstrap-vue.min.js"></script>

<link href="https://unpkg.com/[email protected]/dist/bootstrap-vue.css" rel="stylesheet" />
<link href="https://unpkg.com/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />


<div id="app" class="p-5">
  <template>
  <b-container fluid>
    <!-- User Interface controls -->
    <b-row>
      <b-col lg="6" class="my-1">
        <b-form-group
          label="Sort"
          label-for="sort-by-select"
          label-cols-sm="3"
          label-align-sm="right"
          label-size="sm"
          class="mb-0"
          v-slot="{ ariaDescribedby }"
        >
          <b-input-group size="sm">
            <b-form-select
              id="sort-by-select"
              v-model="sortBy"
              :options="sortOptions"
              :aria-describedby="ariaDescribedby"
              class="w-75"
            >
              <template #first>
                <option value="">-- none --</option>
              </template>
  </b-form-select>

  <b-form-select v-model="sortDesc" :disabled="!sortBy" :aria-describedby="ariaDescribedby" size="sm" class="w-25">
    <option :value="false">Asc</option>
    <option :value="true">Desc</option>
  </b-form-select>
  </b-input-group>
  </b-form-group>
  </b-col>

  <b-col lg="6" class="my-1">
    <b-form-group label="Initial sort" label-for="initial-sort-select" label-cols-sm="3" label-align-sm="right" label-size="sm" class="mb-0">
      <b-form-select id="initial-sort-select" v-model="sortDirection" :options="['asc', 'desc', 'last']" size="sm"></b-form-select>
    </b-form-group>
  </b-col>

  <b-col lg="6" class="my-1">
    <b-form-group label="Filter" label-for="filter-input" label-cols-sm="3" label-align-sm="right" label-size="sm" class="mb-0">
      <b-input-group size="sm">
        <b-form-input id="filter-input" v-model="filter" type="search" placeholder="Type to Search"></b-form-input>

        <b-input-group-append>
          <b-button :disabled="!filter" @click="filter = ''">Clear</b-button>
        </b-input-group-append>
      </b-input-group>
    </b-form-group>
  </b-col>

  <b-col lg="6" class="my-1">
    <b-form-group v-model="sortDirection" label="Filter On" description="Leave all unchecked to filter on all data" label-cols-sm="3" label-align-sm="right" label-size="sm" class="mb-0" v-slot="{ ariaDescribedby }">
      <b-form-checkbox-group v-model="filterOn" :aria-describedby="ariaDescribedby" class="mt-1">
        <b-form-checkbox value="name">Name</b-form-checkbox>
        <b-form-checkbox value="age">Age</b-form-checkbox>
        <b-form-checkbox value="isActive">Active</b-form-checkbox>
      </b-form-checkbox-group>
    </b-form-group>
  </b-col>

  <b-col sm="5" md="6" class="my-1">
    <b-form-group label="Per page" label-for="per-page-select" label-cols-sm="6" label-cols-md="4" label-cols-lg="3" label-align-sm="right" label-size="sm" class="mb-0">
      <b-form-select id="per-page-select" v-model="perPage" :options="pageOptions" size="sm"></b-form-select>
    </b-form-group>
  </b-col>

  <b-col sm="7" md="6" class="my-1">
    <b-pagination v-model="currentPage" :total-rows="totalRows" :per-page="perPage" align="fill" size="sm" class="my-0"></b-pagination>
  </b-col>
  </b-row>

  <!-- Main table element -->
  <b-table :items="items" :fields="fields" :current-page="currentPage" :per-page="perPage" :filter="filter" :filter-included-fields="filterOn" :sort-by.sync="sortBy" :sort-desc.sync="sortDesc" :sort-direction="sortDirection" stacked="md" show-empty small
    @filtered="onFiltered">
    <template #cell(name)="row">
        {{ row.value.first }} {{ row.value.last }}
      </template>

    <template #cell(actions)="row">
        <b-button size="sm" @click="info(row.item, row.index, $event.target)" class="mr-1">
          Info modal
        </b-button>
        <b-button size="sm" @click="row.toggleDetails">
          {{ row.detailsShowing ? 'Hide' : 'Show' }} Details
        </b-button>
      </template>

    <template #row-details="row">
        <b-card>
          <ul>
            <li v-for="(value, key) in row.item" :key="key">{{ key }}: {{ value }}</li>
          </ul>
        </b-card>
      </template>
  </b-table>

  <!-- Info modal -->
  <b-modal :id="infoModal.id" :title="infoModal.title" ok-only @hide="resetInfoModal">
    <pre>{{ infoModal.content }}</pre>
  </b-modal>
  </b-container>
  </template>


</div>

Upvotes: 1

Hiws
Hiws

Reputation: 10334

There's various ways to filter, but the most simple version is simply passing in a string to the filter prop on b-table.

This will search all columns for the string you pass in, so if you bind a data property to a input's v-model and the same data property to the filter property on your table, anything you type in the input will filter the table.

You can read more about how filtering works and some of the other methods in the documentation.

new Vue({
  el: '#app',
  data() {
    return {
      filter: '',
      items: [
        { id: 1, first_name: "Mikkel", last_name: "Hansen", age: 54 },
        { id: 2, first_name: "Kasper", last_name: "Hvidt", age: 42 },
        { id: 3, first_name: "Lasse", last_name: "Boesen", age: 39 },
        { id: 4, first_name: "Kasper", last_name: "Hansen", age: 62 },
        { id: 5, first_name: "Mads", last_name: "Mikkelsen", age: 31 },
      ]
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/[email protected]/dist/bootstrap-vue.min.js"></script>

<link href="https://unpkg.com/[email protected]/dist/bootstrap-vue.css" rel="stylesheet" />
<link href="https://unpkg.com/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />

<div id="app" class="p-5">
  <b-input v-model="filter" placeholder="Filter table.."></b-input>
  <hr />
  <b-table :items="items" :fields="fields" :filter="filter">
  </b-table>
</div>

Upvotes: 5

EMILO
EMILO

Reputation: 473

Is this what you are looking for?

new Vue({
  el: "#app",
  data: {
  Items: [
  {Name: 'Lorem ipsum'},
  {Name: 'consectetur'},
  {Name: 'adipisicing.'}
  ],
  search: ''
  },
  computed: {
  filteredItems() {
  return this.Items.filter(item => item.Name.toLowerCase().includes(this.search.toLowerCase()))
  }
  }
})
.item {
  border: solid black 2px;
  padding: 10px;
  margin: 10px;
}

.search {
  border: solid black 2px;
  padding: 10px;
  margin: 10px;
}
p {
    padding: 10px;
}
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
<p>Found {{filteredItems.length}} items</p>
  <input class="search" type="text" placeholder="Search" v-model="search">
  <div class="item" v-for="item in filteredItems">{{item.Name}}</div>
</div>

Upvotes: -1

Related Questions