react-yajra-datatable
Version:
React component without dependencies to use with yajra laravel-datatables
181 lines (158 loc) • 5.45 kB
JavaScript
import React, {Component} from 'react';
import Header from './Header/Header.js';
import Body from './Body/Body.js';
import Footer from './Footer/Footer.js';
import query from '../services/query';
import debounce from 'lodash';
const requestSearch = (value, regex = false) => ({
value,
regex
});
const DESC = 'desc';
const ASC = 'asc';
const toggleDirection = (direction) => (direction === ASC) ? DESC : ASC;
const DEBOUNCE_DELAY = 500;
export default class DataTable extends Component {
constructor(props) {
super(props);
this.state = {
entriesToShow: 10,
searchInput: '',
currentPage: 0,
orderColumnIndex: 0,
orderColumnDirection: DESC,
refreshing: false,
recordsTotal: 0,
recordsFiltered: 0,
drawCount: 1,
data: []
};
this.updateTableState = this.updateTableState.bind(this);
this.handleSetEntriesToShow = this.handleSetEntriesToShow.bind(this);
this.handleSetSearchInput = this.handleSetSearchInput.bind(this);
this.handleSetPage = this.handleSetPage.bind(this);
this.handleSetOrderColumn = this.handleSetOrderColumn.bind(this);
this.debouncedDraw = debounce(this.debouncedDraw.bind(this), (this.props.debounceDelay || DEBOUNCE_DELAY));
}
getStartIndex() {
return this.state.currentPage * this.state.entriesToShow;
}
updateTableState(response) {
const { recordsTotal, recordsFiltered, data, draw } = this.getResponseData(response.data);
this.setState({
recordsTotal: recordsTotal,
recordsFiltered: recordsFiltered,
data: data,
drawCount: (draw + 1),
refreshing: false,
});
}
getResponseData(data) {
return (this.props.responseDataGetter) ? this.props.responseDataGetter(data) : data;
}
handleSetEntriesToShow(entriesToShow) {
this.setState({
entriesToShow
}, () => this.draw());
}
handleSetSearchInput(searchInput) {
this.setState({
searchInput
}, () => this.debouncedDraw());
}
debouncedDraw() {
this.draw();
}
handleSetPage(page) {
if (this.state.currentPage != page) {
this.setState({
currentPage: page
}, () => this.draw());
}
}
handleSetOrderColumn(columnIndex, columnDirection = null) {
if (columnIndex === this.state.orderColumnIndex) {
columnDirection = columnDirection || toggleDirection(this.state.orderColumnDirection);
} else {
columnDirection = columnDirection || DESC;
}
this.setState({
orderColumnIndex: columnIndex,
orderColumnDirection: columnDirection,
}, () => this.draw());
}
getBodyData() {
return this.state.data.slice(this.getStartIndex(), this.state.entriesToShow);
}
getColumns() {
return this.props.columns.slice(0).map(column => (Object.assign({
searchable: true,
orderable: true,
search: requestSearch(''),
}, column)));
}
getOrderForRequest() {
return [{
column: this.state.orderColumnIndex,
dir: this.state.orderColumnDirection
}];
}
getRequestData() {
return {
columns: this.getColumns(),
start: this.getStartIndex(),
length: this.state.entriesToShow,
search: requestSearch(this.state.searchInput),
order: this.getOrderForRequest(),
draw: this.state.drawCount
};
}
refresh() {
query({
url: this.props.url,
method: this.props.method || 'get',
data: this.getRequestData()
}).then(this.updateTableState);
}
componentDidMount() {
this.draw();
}
draw() {
this.setState({
refreshing: true
}, () => this.refresh());
}
getStyleProps() {
return {
bordered: this.props.bordered || true,
condensed: this.props.condensed || true,
alternated: this.props.alternated || true
};
}
render() {
return (
<div>
<Header
entriesToShow={this.state.entriesToShow}
searchInput={this.state.searchInput}
setEntriesToShow={this.handleSetEntriesToShow}
setSearchInput={this.handleSetSearchInput} />
<Body
columns={this.getColumns()}
data={this.state.data}
orderColumnDirection={this.state.orderColumnDirection}
orderColumnIndex={this.state.orderColumnIndex}
setOrderColumn={this.handleSetOrderColumn}
styles={this.getStyleProps()}/>
<Footer
currentPage={this.state.currentPage}
setPage={this.handleSetPage}
entriesToShow={this.state.entriesToShow}
recordsFiltered={this.state.recordsFiltered}
recordsTotal={this.state.recordsTotal}
dataLength={this.state.data.length}
refreshing={this.state.refreshing}/>
</div>
);
}
}