Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

eggplantSword's avatar

Element-ui table combine pagination and search

Is there a way I could combine these two examples to be able to not only search but have pagination on my Element-ui tables?

These are the two examples,

Search: https://codepen.io/AndrewThian/pen/QdeOVa?editors=1010

Pagination: https://codepen.io/reijnemans/pen/dyoaxGv

This is my code, I have only implemented the pagination example

<el-table
    :data="displayData"
    style="width: 100%">
    <el-table-column
        prop="name"
        label="Nombre">
    </el-table-column>
</el-table>

<el-divider></el-divider>

<div style="text-align: center">
    <el-pagination
        background
        layout="prev, pager, next"
        @current-change="handleCurrentChange"
        :page-size="pageSize"
        :total="categories.length">
    </el-pagination>
</div>
data() {
    return {
        page: 1,
        pageSize: 4
    }
},
computed: {
    displayData() {
        if (!this.categories || this.categories.length === 0) return [];
        return this.categories.slice(this.pageSize * this.page - this.pageSize, this.pageSize * this.page)
    }
},
methods: {
    handleCurrentChange(val) {
        this.page = val;
    },
}

The element-ui table here shows an example with search (https://element.eleme.io/#/en-US/component/table#table-with-custom-header) but I'm unsure how to combine them while still having both working, for example if I search and the result is less than the pageSize then display only one page for the pagination, and if there are more then have the pagination work for the search results.

How can I combine both?

0 likes
8 replies
eggplantSword's avatar
eggplantSword
OP
Best Answer
Level 9

This is the solution

 <el-table
    :data="displayData"
    style="width: 100%">
    <el-table-column
        prop="name"
        label="Nombre">
    </el-table-column>
</el-table>

<el-divider></el-divider>

<div style="text-align: center">
    <el-pagination
        background
        layout="prev, pager, next"
        @current-change="handleCurrentChange"
        :page-size="pageSize"
        :total="total">
    </el-pagination>
</div>
data() {
    return {
       filtered: [],
       search: '',
       page: 1,
       pageSize: 4,
       total: 0
    }
},
computed: {
    displayData() {
        if(this.search == null) return this.categories;
      
        this.filtered = this.categories.filter(data => !this.search || data.name.toLowerCase().includes(this.search.toLowerCase()));
        
        this.total = this.filtered.length;

        return this.filtered.slice(this.pageSize * this.page - this.pageSize, this.pageSize * this.page);
    }
},
methods: {
    handleCurrentChange(val) {
        this.page = val;
    },
}
ShammasTA's avatar

@msslgomez From where this.category comes? In my case computed is calling before API inside methods, so the value I'm taking in place of this.categories return null for the first time and it throws the error

deewhy's avatar

Hello@msslgomez

tried this code but whenever I go next page, search is not working anymore. any work around for this?

eggplantSword's avatar

@deewhy I honestly hadn't noticed... I'm trying to see what can be done to fix this mistake. The search is working but it's not doing the search on all the items, it seems to be searching on the items on the current page and not the pages before.

eggplantSword's avatar

@deewhy I got it

The html/vue code and the method stays the same, the error is in the displayData, this is the solution

searching() {
    if (!this.search) {
        this.total = this.categories.length;
        return this.categories;
    }
    this.page = 1;
    return this.categories.filter(data => data.name.toLowerCase().includes(this.search.toLowerCase()));
},
displayData() {
    this.total = this.searching.length;

    return this.searching.slice(this.pageSize * this.page - this.pageSize, this.pageSize * this.page);
}
3 likes
psalcedodev's avatar

Just in case anyone wants a dynamic table with what's offered above and with multiple props to search, here it is.

<template>
  <div>
    <el-table
      :data="displayData"
      :default-sort="tableSort ? { prop: tableSortBy, order: tableSortOrder } : { prop: '', order: '' }"
      :height="tableHeight"
      :table-layout="tableLayout"
      highlight-current-row
      @row-click="onRowClick"
    >
      <el-table-column
        class="tw-cursor-pointer"
        v-for="column in columns"
        :key="column.label"
        :label="column.label"
        :prop="column.prop"
        :formatter="column.formatter"
        :min-width="column.minWidth"
        :sortable="column.sortable"
      >
        <template #default="scope">
          <div v-if="column.funcProp" v-html="column.funcProp(scope.row)"></div>
        </template>
      </el-table-column>
      <el-table-column width="300" align="right">
        <template #header>
          <div class="tw-mt-1 tw-relative tw-rounded-md tw-shadow-sm">
            <div class="tw-absolute tw-inset-y-0 tw-left-0 tw-pl-3 tw-flex tw-items-center tw-pointer-events-none">
              <SearchIcon class="tw-h-5 tw-w-5 tw-text-gray-400" aria-hidden="true" />
            </div>
            <input
              v-model="search"
              type="search"
              class="focus:tw-ring-indigo-500 focus:tw-border-indigo-500 tw-block tw-w-full tw-pl-10 sm:tw-text-sm tw-border-gray-300 tw-rounded-md"
              :placeholder="`Search by ${searchBy !== '' ? searchBy : 'name'}`"
            />
          </div>
        </template>
        <template #default="scope">
          <el-button size="small" @click="handleEdit(scope.row)">Edit</el-button>
          <el-button size="small" type="danger" @click="handleDelete(scope.row)">Delete</el-button>
        </template>
      </el-table-column>
    </el-table>

    <div class="tw-mt-4">
      <el-pagination
        background
        @size-change="changePerPage"
        @current-change="changeCurrentPage"
        @currentPage="currentPage"
        :page-size="perPage"
        :page-sizes="[20, 30, 40, 50, 100]"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
      >
      </el-pagination>
    </div>
  </div>
</template>

<script>
import { SearchIcon } from '@heroicons/vue/solid'
export default {
  components: { SearchIcon },
  props: {
    data: Array,
    columns: Array,
    tableLayout: {
      type: String,
      default: 'auto',
      required: false,
    },
    tableSort: {
      type: Boolean,
      default: false,
      required: false,
    },
    tableSortBy: {
      type: String,
      default: '',
      required: false,
    },
    tableSortOrder: {
      type: String,
      default: 'asc',
      required: false,
    },
    tableHeight: {
      type: String,
      default: '70vh',
      required: false,
    },
    searchBy: {
      type: Array,
      default: ['name'],
      required: false,
    },
  },
  data() {
    return {
      filtered: [],
      search: '',
      page: 1,
      currentPage: 1,
      perPage: 20,
      total: 0,
    }
  },
  computed: {
    displayData() {
      if (this.search == null) return this.data
      this.filtered = this.data.filter(
        (data) =>
          !this.search ||
          this.searchBy.some((item) => data[item].toString().toLowerCase().includes(this.search.toLowerCase()))
      )

      this.total = this.filtered.length

      return this.filtered.slice(this.perPage * this.currentPage - this.perPage, this.perPage * this.currentPage)
    },
  },
  methods: {
    onRowClick(row) {
      this.$emit('rowclick', row)
    },
    handleEdit(row) {
      this.$emit('edit', row)
    },
    handleDelete(row) {
      this.$emit('delete', row)
    },
    changeCurrentPage(val) {
      this.currentPage = val
    },

    changePerPage(val) {
      this.perPage = val
    },
  },
}
</script>

Your component calling the Dynamic table component

data() {
    return {
      columns: [
        {
          label: 'Name',
          prop: 'name',
          sortable: true,
        },
        {
          label: 'Email',
          prop: 'email',
          sortable: true,
        },
	]}
},
methods: {
    handleEdit(row) {
      console.log(row)
    },
    handleDelete(row) {
      console.log(row.id)
    },
  },

<Table
          :data="data"
          :columns="columns"
          table-layout="fixed"
          table-height="70vh"
          @edit="handleEdit"
          @delete="handleDelete"
          @rowclick="handleEdit"
          :search-active="true"
          :table-sort="true"
          :table-sort-by="'name'"
          :table-sort-order="'asc'"
          :search-by="['name', 'email']"
        />

You can now feed data to your dynamic table and user over and over!!

I'm sure there are things to improve, but that's up to you now :)

amineamiri's avatar

@psalcedodev thank you ,

im stuck with Inertia js and elment-ui table any tutorial please ?

i try to set pagination but i cant fin the route to links in the change page function : <el-pagination v-if="items.last_page > 1" background layout="total, prev, pager, next" :total="items.total" :page-size="items.per_page" :current-page="items.current_page" @update:current-page="items.current_page" @current-change="handleCurrentChange" /> i wanna make something like this : const handleCurrentChange = (id) => { Inertia.get(route('items.links', id)) }

thanx a lot for your help

Please or to participate in this conversation.