TanStack / table

🤖 Headless UI for building powerful tables & datagrids for TS/JS - React-Table, Vue-Table, Solid-Table, Svelte-Table
https://tanstack.com/table
MIT License
24.98k stars 3.07k forks source link

Manual Pagination disables the sorting and column filtering #1040

Closed kala2 closed 5 years ago

kala2 commented 6 years ago

I have a table which displays clinics. I have also a onPageChange prop which handles the pageIndex and then i fetch the data based on that page. Below is my table configuration

import 'react-table/react-table.css'
import React, { Component } from 'react';
import ClinicFormComponent from './newClinicForm';
import SearchFormComponent from '../search/searchForm';
import { connect } from 'react-redux';
import { fetchClinics, fetchClinic, deleteClinic, searchClinics, pushBreadcrumb, popBreadcrumb } from '../../actions/index.js';
import { toast } from 'react-toastify';
import ReactTable from 'react-table'
import store from '../../helpers/store';
import { ic_search } from 'react-icons-kit/md/ic_search';
import SvgIcon from 'react-icons-kit';
require('normalize.css/normalize.css');
// require('styles/App.css');
class ClinicsPage extends Component {

  constructor() {
    super();
    this.onPageChange = this.onPageChange.bind(this);
  }

  componentDidMount(){
    this.props.searchClinics({ country: 'Australia' });
  }

  onPageChange(pageIndex) {
      this.props.fetchClinics(pageIndex, null);
  }

  render() {
    let { devs } = this.props;

    const columns = [{
        Header: 'Id',
        accessor: 'id' // String-based value accessors!
      }, {
        Header: 'Name',
        accessor: 'name'
      }, {
        Header: 'Description', // Required because our accessor is not a string
        accessor: 'description',
        sortable: true
        // accessor: d => d.friend.name // Custom value accessors!
      },
      {
        Header: 'Country', // Required because our accessor is not a string
        accessor: 'country',
        sortable: true
        // accessor: d => d.friend.name // Custom value accessors!
      },
      {
        Header: 'Area', // Required because our accessor is not a string
        accessor: 'area',
        sortable: true
        // accessor: d => d.friend.name // Custom value accessors!
      },
      {
        Header: 'Latitude', // Required because our accessor is not a string
        accessor: 'latitude',
        sortable: true
        // accessor: d => d.friend.name // Custom value accessors!
      },
      {
        Header: 'Longitude', // Required because our accessor is not a string
        accessor: 'longitude',
        sortable: true
        // accessor: d => d.friend.name // Custom value accessors!
      },
      {
        Header: 'Tags', // Required because our accessor is not a string
        accessor: 'tags',
        sortable: true,
        Cell: (row) => {if (row.original.tags.length>1) { return row.original.tags.join(', ') } else { return row.original.tags } }
      },
      {
        Header: () => <span className="text-center">Actions</span>,
        accessor: 'id',
        id: 'actions',
        sortable: true,
        Cell: (row) => (<span><button className="text-center btn btn-primary margin_right_5" onClick={()=>{this.props.history.push('/editClinic/'+ row.original.id)}}>Edit</button ><button className="text-center btn btn-danger" onClick={()=>{this.props.deleteClinic(row.original.id, row.original)}}>Delete</button ></span>)
      }
    ]

    return (
      <div className="wrap">
          <div className="row margin_top_10 margin_bottom_5">
              <div className="col-sm-6">
                  <a className="btn btn-link color btn_alt" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="collapseExample2" onClick={this.handleClickForm}>NEW CLINIC</a>
              </div>
              <div className="col-sm-6">
                  <a className="nav-link float_right search-clinic-btn" data-toggle="collapse" onClick={this.handleClickFormSearch} role="button" aria-expanded="false" aria-controls="collapseExample"><span className="search_label">Search data entries...</span> <SvgIcon size={25} icon={ic_search}/></a>
              </div>
          </div>
          <div id="nav-tabContent">
            <ReactTable
              data={devs.clinics}
              pageSizeOptions= {[10]}
              defaultPageSize= {10}
              columns={columns}
              pages={devs.paginationData.totalPages || ''}
              sortable={true}
              multiSort={true}
              //manual
              filterable
              page={devs.paginationData.pageNumber}
              loading={devs.isFetching}
              onPageChange={this.onPageChange}
              noDataText='No Data Found'
              className='-striped -highlight'
              />
          </div>
      </div>
    );
  }
}
function mapStateToProps(state) {
  return {
    devs: state.reducer.devs
  }
}

Notice that i have disabled manual prop. If i enable the manual prop then i can navigate through next and previous pages but i cannot sort or filter the data.

With the manual prop disabled the filtering and the sorting works correct but when i navigate in the next page the table in this particular page is showed empty. The first page displays correct the first 10 data. Also i have tested the api and returns correct the next 10 data.

Also the devs.paginationData.pageNumber is updated correctly, and the page is changing with the correctly page number on the table

Is there any workaround? To keep both server side pagination and also the default sorting and filtering?

tannerlinsley commented 5 years ago

This feature/issue has been tagged as one that will likely be fixed or improved in the next major release of React-Table. This release is expected to be completed in the next 6 - 8 months. Please see #1143 for more detail. If you believe this feature can be easily fixed, we invite you to fork the project, attempt the fix, and use it until the latest version is available. If the fix is simple enough, we will also consider it as a PR to the current version.

danmouracunha commented 5 years ago

Is this issue solved?

Anahkiasen commented 5 years ago

I'm bumping into the same issue, is there a way to selectively disable things? I just want API pagination but keep the sorting like the OP

Jiglet commented 5 years ago

Having the same issue. Please keep us updated!

ramonparisg commented 5 years ago

Hello! Any news about this?

hshelbur commented 4 years ago

Has anyone found a workaround for this issue?

usman10scorpio commented 4 years ago

Hi I have applied all the manual pagination but the filtering is not working :( I wish I knew this before implementing it.

vardan-arm commented 4 years ago

I had a similar problem (using version 6.8.5).

You need to set onFetchData option as well. It is called both on changing the page and on sorting/filtering. Overall, my simplified component looks like this:

const TableViewComponent = (
  props
) => {

  // some other logic ....

  return (
    <div className={classes.container}>
      <ReactTable
        loading={isLoading}
        columns={columns}
        manual
        data={dataToRender}
        pages={pagesCount}
        pageSizeOptions={pageSizeOptions}
        pageSize={recordsPerPage}
        onPageSizeChange={pageSize => {
          setPageNumber(0);
          setRecordsPerPage(pageSize);

          getNewData({
            rowLimit: pageSize,
            rowOffset: firstRecordOffset.current,
          });
        }}
        page={pageNumber}
        filterable
        filtered={tableFiltered}
        onFilteredChange={filtered => setTableFiltered(filtered)}
        sorted={tableSorted}
        onSortedChange={sorted => setTableSorted(sorted)}
        defaultFiltered={[]}
        onFetchData={state => {
          const newData = fetchData(
            data,
            state.pageSize,
            state.page,
            state.sorted,
            state.filtered,
          );
          setDataToRender(newData);
        }}
        onPageChange={pageIndex => {
          setPageNumber(pageIndex);

          getNewData({
            rowLimit,
            rowOffset: pageIndex * rowLimit + firstRecordOffset.current,
          });
        }}
        defaultPageSize={rowLimit}
        multiSort={false}
        className={`-striped -highlight ${classes.table}`}
      />
    </div>
  );
};
minaairsupport commented 4 years ago

could we add manual pagination option to sperate pagination way from sorting and filtering which make sense