UNPKG

@ashvin27/react-datatable

Version:

ReactDatatable is a component which provide ability to create multifunctional table using single component like jQuery Datatable

813 lines (746 loc) 33.4 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _server = require('react-dom/server'); var _server2 = _interopRequireDefault(_server); var _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash); require('./assets/css/style.css'); var _TableHeader = require('./components/TableHeader'); var _TableHeader2 = _interopRequireDefault(_TableHeader); var _TableFooter = require('./components/TableFooter'); var _TableFooter2 = _interopRequireDefault(_TableFooter); var _style = require('./style'); var _style2 = _interopRequireDefault(_style); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** * This is the React Component for ReactDatatable * * @package ReactDatatable * @author Ashvin Patel(patelash212@gmail.com) * @date 14 Dec, 2018 */ var ReactDatatable = function (_Component) { _inherits(ReactDatatable, _Component); function ReactDatatable(props) { _classCallCheck(this, ReactDatatable); var _this = _possibleConstructorReturn(this, (ReactDatatable.__proto__ || Object.getPrototypeOf(ReactDatatable)).call(this, props)); _this.exportExcelRef = _react2.default.createRef(); _this.sortColumn = _this.sortColumn.bind(_this); _this.numPages = _this.numPages.bind(_this); _this.exportToExcel = _this.exportToExcel.bind(_this); _this.exportToPDF = _this.exportToPDF.bind(_this); _this.exportToCSV = _this.exportToCSV.bind(_this); _this.onChange = _this.onChange.bind(_this); _this.filterRecords = _this.filterRecords.bind(_this); _this.filterData = _this.filterData.bind(_this); _this.sortRecords = _this.sortRecords.bind(_this); _this.config = { button: { excel: props.config && props.config.button && props.config.button.excel ? props.config.button.excel : false, print: props.config && props.config.button && props.config.button.print ? props.config.button.print : false, csv: props.config && props.config.button && props.config.button.csv ? props.config.button.csv : false, extra: props.config && props.config.button && props.config.button.extra ? props.config.button.extra : false }, filename: props.config && props.config.filename ? props.config.filename : "table", key_column: props.config && props.config.key_column ? props.config.key_column : "id", language: { length_menu: props.config && props.config.language && props.config.language.length_menu ? props.config.language.length_menu : "Show _MENU_ records per page", filter: props.config && props.config.language && props.config.language.filter ? props.config.language.filter : "Search in records...", info: props.config && props.config.language && props.config.language.info ? props.config.language.info : "Showing _START_ to _END_ of _TOTAL_ entries", pagination: { first: props.config && props.config.language && props.config.language.pagination && props.config.language.pagination.first ? props.config.language.pagination.first : "First", previous: props.config && props.config.language && props.config.language.pagination && props.config.language.pagination.previous ? props.config.language.pagination.previous : "Previous", next: props.config && props.config.language && props.config.language.pagination && props.config.language.pagination.next ? props.config.language.pagination.next : "Next", last: props.config && props.config.language && props.config.language.pagination && props.config.language.pagination.last ? props.config.language.pagination.last : "Last" }, no_data_text: props.config && props.config.language && props.config.language.no_data_text ? props.config.language.no_data_text : 'No rows found', loading_text: props.config && props.config.language && props.config.language.loading_text ? props.config.language.loading_text : "Loading..." }, length_menu: props.config && props.config.length_menu ? props.config.length_menu : [10, 25, 50, 75, 100], show_length_menu: props.config.show_length_menu != undefined ? props.config.show_length_menu : true, show_filter: props.config.show_filter != undefined ? props.config.show_filter : true, show_pagination: props.config.show_pagination != undefined ? props.config.show_pagination : true, show_info: props.config.show_info != undefined ? props.config.show_info : true, show_first: props.config.show_first != undefined ? props.config.show_first : true, show_last: props.config.show_last != undefined ? props.config.show_last : true, pagination: props.config.pagination ? props.config.pagination : 'basic' }; _this.state = { is_temp_page: false, filter_value: "", page_size: props.config.page_size ? props.config.page_size : 10, page_number: 1, sort: props.config && props.config.sort ? props.config.sort : false }; return _this; } _createClass(ReactDatatable, [{ key: 'filterRecords', value: function filterRecords(e) { var _this2 = this; var value = e.target.value; this.setState({ page_number: 1, filter_value: value }, function () { _this2.onChange(); }); } }, { key: 'changePageSize', value: function changePageSize(e) { var _this3 = this; var value = e.target.value; this.setState({ page_size: value }, function () { _this3.onChange(); }); } }, { key: 'sortColumn', value: function sortColumn(event, column, sortOrder) { var _this4 = this; if (!column.sortable) return false; var newSortOrder = sortOrder == "asc" ? "desc" : "asc"; this.setState({ 'sort': { column: column.key, order: newSortOrder } }, function () { _this4.onChange(); }); } }, { key: 'paginate', value: function paginate(records) { var page_size = this.state.page_size; var page_number = this.state.page_number; --page_number; // because pages logically start with 1, but technically with 0 return records.slice(page_number * page_size, (page_number + 1) * page_size); } }, { key: 'numPages', value: function numPages(totalRecord) { return Math.ceil(totalRecord / this.state.page_size); } }, { key: 'isLast', value: function isLast() { // because for empty records page_number will still be 1 if (this.pages == 0) { return true; } if (this.state.page_number == this.pages) { return true; } else { return false; } } }, { key: 'isFirst', value: function isFirst() { if (this.state.page_number == 1) { return true; } else { return false; } } }, { key: 'goToPage', value: function goToPage(e, pageNumber) { var _this5 = this; e.preventDefault(); if (this.state.page_number == pageNumber) { return; } var pageState = { previous_page: this.state.page_number, current_page: pageNumber }; this.setState({ is_temp_page: false, page_number: pageNumber }, function () { _this5.props.onPageChange(pageState); _this5.onChange(); }); } }, { key: 'firstPage', value: function firstPage(e) { e.preventDefault(); if (this.isFirst()) return; this.goToPage(e, 1); } }, { key: 'lastPage', value: function lastPage(e) { e.preventDefault(); if (this.isLast()) return; this.goToPage(e, this.pages); } }, { key: 'previousPage', value: function previousPage(e) { e.preventDefault(); if (this.isFirst()) return false; this.goToPage(e, this.state.page_number - 1); } }, { key: 'nextPage', value: function nextPage(e) { e.preventDefault(); if (this.isLast()) return; this.goToPage(e, parseInt(this.state.page_number) + 1); } }, { key: 'onPageChange', value: function onPageChange(e) { var isInputChange = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; if (isInputChange) { this.setState({ is_temp_page: true, temp_page_number: e.target.value }); } else { if (e.key === 'Enter') { var pageNumber = e.target.value; this.goToPage(e, pageNumber); } } } }, { key: 'onPageBlur', value: function onPageBlur(e) { var pageNumber = e.target.value; this.goToPage(event, pageNumber); } }, { key: 'strip', value: function strip(html) { var doc = new DOMParser().parseFromString(html, 'text/html'); return doc.body.textContent || ""; } }, { key: 'getExportHtml', value: function getExportHtml() { var tableHtml = "<table>"; tableHtml += "<thead>"; tableHtml += "<tr>"; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = this.props.columns[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var column = _step.value; tableHtml += "<th>" + column.text + "</th>"; } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } tableHtml += "</tr>"; tableHtml += "</thead>"; tableHtml += "<tbody>"; // Filter records before export var filterRecords = this.props.records; if (this.props.dynamic === false) { var records = this.sortRecords(), filterValue = this.state.filter_value; filterRecords = records; if (filterValue) { filterRecords = this.filterData(records); } } for (var i in filterRecords) { var record = filterRecords[i]; tableHtml += "<tr>"; var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = this.props.columns[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var _column = _step2.value; if (_column.cell && typeof _column.cell === "function") { var cellData = _server2.default.renderToStaticMarkup(_column.cell(record, i)); cellData = this.strip(cellData); tableHtml += "<td>" + cellData + "</td>"; } else if (record[_column.key]) { tableHtml += "<td>" + record[_column.key] + "</td>"; } else { tableHtml += "<td></td>"; } } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } tableHtml += "</tr>"; } tableHtml += "</tbody>"; tableHtml += "</table>"; return tableHtml; } }, { key: 'exportToExcel', value: function exportToExcel() { var downloadLink = void 0, dataType = 'application/vnd.ms-excel'; var tableHtml = this.getExportHtml(); // Specify file name var filename = this.config.filename ? this.config.filename + '.xls' : 'table.xls'; // Create download link element downloadLink = document.createElement("a"); if (navigator.msSaveOrOpenBlob) { var blob = new Blob(['\uFEFF', tableHtml], { type: dataType }); navigator.msSaveOrOpenBlob(blob, filename); } else { // Create a link to the file downloadLink.href = 'data:' + dataType + ', ' + tableHtml; // Setting the file name downloadLink.download = filename; //triggering the function downloadLink.click(); } } }, { key: 'exportToPDF', value: function exportToPDF() { var tableHtml = this.getExportHtml(); var style = "<style>"; style = style + "table {width: 100%;font: 17px Calibri;}"; style = style + "table, th, td {border: solid 1px #DDD; border-collapse: collapse;"; style = style + "padding: 2px 3px;text-align:left;}"; style = style + "</style>"; var win = window.open('', '_blank'); win.document.write('<html><head>'); win.document.write('<title>' + this.config.filename + '</title>'); win.document.write(style); win.document.write('</head>'); win.document.write('<body>'); win.document.write('<h1>' + this.config.filename + '</h1>'); win.document.write(tableHtml); win.document.write('</body></html>'); win.print(); win.close(); } }, { key: 'convertToCSV', value: function convertToCSV(objArray) { var array = (typeof objArray === 'undefined' ? 'undefined' : _typeof(objArray)) != 'object' ? JSON.parse(objArray) : objArray; var str = ''; for (var i = 0; i < array.length; i++) { var line = ''; for (var index in array[i]) { if (line != '') line += ','; line += array[i][index]; } str += line + '\r\n'; } return str; } }, { key: 'exportToCSV', value: function exportToCSV() { var headers = {}; // add columns in sheet array var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = this.props.columns[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var column = _step3.value; headers[column.key] = '"' + column.text + '"'; } // Filter records before export } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } var filterRecords = this.props.records; if (this.props.dynamic === false) { var _records = this.sortRecords(), filterValue = this.state.filter_value; filterRecords = _records; if (filterValue) { filterRecords = this.filterData(_records); } } var records = []; // add data rows in sheet array for (var i in filterRecords) { var record = filterRecords[i], newRecord = {}; var _iteratorNormalCompletion4 = true; var _didIteratorError4 = false; var _iteratorError4 = undefined; try { for (var _iterator4 = this.props.columns[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { var _column2 = _step4.value; if (_column2.cell && typeof _column2.cell === "function") { var cellData = _server2.default.renderToStaticMarkup(_column2.cell(record, i)); cellData = this.strip(cellData); newRecord[_column2.key] = cellData; } else if (record[_column2.key]) { var colValue = record[_column2.key]; colValue = typeof colValue === "string" ? colValue.replace(/"/g, '""') : colValue; newRecord[_column2.key] = '"' + colValue + '"'; } else { newRecord[_column2.key] = ""; } } } catch (err) { _didIteratorError4 = true; _iteratorError4 = err; } finally { try { if (!_iteratorNormalCompletion4 && _iterator4.return) { _iterator4.return(); } } finally { if (_didIteratorError4) { throw _iteratorError4; } } } records.push(newRecord); } if (headers) { records.unshift(headers); } // Convert Object to JSON var jsonObject = JSON.stringify(records); var csv = this.convertToCSV(jsonObject); var exportedFilename = this.config.filename + '.csv' || 'export.csv'; var blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); if (navigator.msSaveBlob) { // IE 10+ navigator.msSaveBlob(blob, exportedFilename); } else { var link = document.createElement("a"); if (link.download !== undefined) { // feature detection // Browsers that support HTML5 download attribute var url = URL.createObjectURL(blob); link.setAttribute("href", url); link.setAttribute("download", exportedFilename); link.style.visibility = 'hidden'; document.body.appendChild(link); link.click(); link.remove(); } } } }, { key: 'onChange', value: function onChange() { var tableData = { filter_value: this.state.filter_value, page_number: this.state.page_number, page_size: this.state.page_size, sort_order: this.state.sort }; this.props.onChange(tableData); } }, { key: 'filterData', value: function filterData(records) { var _this6 = this; var filterValue = this.state.filter_value; return records.filter(function (record) { var allow = false; _lodash2.default.each(_this6.props.columns, function (column, key) { if (record[column.key]) { allow = _lodash2.default.includes(record[column.key].toString().toLowerCase(), filterValue.toString().toLowerCase()) ? true : allow; } }); return allow; }); } }, { key: 'sortRecords', value: function sortRecords() { var _this7 = this; if (this.state.sort) { return _lodash2.default.orderBy(this.props.records, function (o) { var colVal = o[_this7.state.sort.column]; var typeofColVal = typeof colVal === 'undefined' ? 'undefined' : _typeof(colVal); if (typeofColVal == "string") { if (isNaN(colVal)) { return new String(colVal.toLowerCase()); } else { return new Number(colVal); } } else if (typeofColVal == "number") { return new Number(colVal); } }, [this.state.sort.order]); } else { return this.props.records; } } }, { key: 'render', value: function render() { var _this8 = this; var filterRecords = void 0, totalRecords = void 0, pages = void 0, isFirst = void 0, isLast = void 0; if (this.props.dynamic === false) { var records = this.props.onSort ? this.props.onSort(this.state.sort.column, this.props.records, this.state.sort.order) : this.sortRecords(), filterValue = this.state.filter_value; filterRecords = records; if (filterValue) { filterRecords = this.filterData(records); } totalRecords = Array.isArray(filterRecords) ? filterRecords.length : 0; pages = this.pages = this.numPages(totalRecords); isFirst = this.isFirst(); isLast = this.isLast(); filterRecords = Array.isArray(filterRecords) ? this.paginate(filterRecords) : []; } else { filterRecords = this.props.records; totalRecords = this.props.total_record; pages = this.pages = this.numPages(totalRecords); isFirst = this.isFirst(); isLast = this.isLast(); } var startRecords = this.state.page_number * this.state.page_size - (this.state.page_size - 1); var endRecords = this.state.page_size * this.state.page_number; endRecords = endRecords > totalRecords ? totalRecords : endRecords; var lengthMenuText = this.config.language.length_menu; lengthMenuText = lengthMenuText.split('_MENU_'); var paginationInfo = this.config.language.info; paginationInfo = paginationInfo.replace('_START_', this.state.page_number == 1 ? 1 : startRecords); paginationInfo = paginationInfo.replace('_END_', endRecords); paginationInfo = paginationInfo.replace('_TOTAL_', totalRecords); return _react2.default.createElement( 'div', { className: 'as-react-table', id: this.props.id ? this.props.id + "-container" : "" }, _react2.default.createElement(_TableHeader2.default, { config: this.config, id: this.props.id, lengthMenuText: lengthMenuText, recordLength: this.props.dynamic ? this.props.total_record : this.props.records.length, filterRecords: this.filterRecords.bind(this), changePageSize: this.changePageSize.bind(this), exportToExcel: this.exportToExcel.bind(this), exportToCSV: this.exportToCSV.bind(this), exportToPDF: this.exportToPDF.bind(this), extraButtons: this.props.extraButtons }), _react2.default.createElement( 'div', { className: 'row table-body asrt-table-body', style: _style2.default.table_body, id: this.props.id ? this.props.id + "-table-body" : "" }, _react2.default.createElement( 'div', { className: 'col-md-12' }, _react2.default.createElement( 'table', { className: this.props.className, id: this.props.id }, _react2.default.createElement( 'thead', { className: this.props.tHeadClassName ? this.props.tHeadClassName : '' }, _react2.default.createElement( 'tr', null, this.props.columns.map(function (column, index) { var classText = column.sortable ? "sortable " : "", width = column.width ? column.width : "", align = column.align ? column.align : "", sortOrder = "", columnStyle = {}; if (column.sortable && _this8.state.sort.column == column.key) { sortOrder = _this8.state.sort.order; classText += sortOrder ? " " + sortOrder : ""; columnStyle = sortOrder == "asc" ? _style2.default.sort_asc : _style2.default.sort_desc; } classText += " text-" + align; if (column.TrOnlyClassName) classText += " " + column.TrOnlyClassName; return _react2.default.createElement( 'th', { key: column.key ? column.key : column.text, className: classText, width: width, style: columnStyle, onClick: function onClick(event) { return _this8.sortColumn(event, column, sortOrder); } }, column.text ); }) ) ), _react2.default.createElement( 'tbody', null, this.props.loading === true ? _react2.default.createElement( 'tr', null, _react2.default.createElement( 'td', { colSpan: this.props.columns.length, className: 'asrt-td-loading', align: 'center' }, _react2.default.createElement( 'div', { className: 'asrt-loading-textwrap' }, _react2.default.createElement( 'span', { className: 'asrt-loading-text' }, this.config.language.loading_text ) ) ) ) : filterRecords.length ? filterRecords.map(function (record, rowIndex) { rowIndex = _lodash2.default.indexOf(_this8.props.records, record); return _react2.default.createElement( 'tr', { key: record[_this8.config.key_column], onClick: function onClick(e) { return _this8.props.onRowClicked(e, record, rowIndex); } }, _this8.props.columns.map(function (column, colIndex) { if (column.cell && typeof column.cell === "function") { return _react2.default.createElement( 'td', { className: column.className, key: column.key ? column.key : column.text }, column.cell(record, rowIndex) ); } else if (record[column.key]) { return _react2.default.createElement( 'td', { className: column.className, key: column.key ? column.key : column.text }, record[column.key] ); } else { return _react2.default.createElement('td', { className: column.className, key: column.key ? column.key : column.text }); } }) ); }) : _react2.default.createElement( 'tr', null, _react2.default.createElement( 'td', { colSpan: this.props.columns.length, align: 'center' }, this.config.language.no_data_text ) ) ) ) ) ), _react2.default.createElement(_TableFooter2.default, { config: this.config, id: this.props.id, isFirst: isFirst, isLast: isLast, paginationInfo: paginationInfo, pages: pages, page_number: this.state.page_number, is_temp_page: this.state.is_temp_page, temp_page_number: this.state.temp_page_number, firstPage: this.firstPage.bind(this), lastPage: this.lastPage.bind(this), previousPage: this.previousPage.bind(this), nextPage: this.nextPage.bind(this), goToPage: this.goToPage.bind(this), changePageSize: this.changePageSize.bind(this), onPageChange: this.onPageChange.bind(this), onPageBlur: this.onPageBlur.bind(this) }) ); } }]); return ReactDatatable; }(_react.Component); /** * Define component display name */ ReactDatatable.displayName = 'ReactDatatable'; /** * Define defaultProps for this component */ ReactDatatable.defaultProps = { id: "as-react-datatable", className: "table table-bordered table-striped", columns: [], config: { button: { excel: false, print: false, csv: false }, filename: "table", key_column: "id", language: { length_menu: "Show _MENU_ records per page", filter: "Search in records...", info: "Showing _START_ to _END_ of _TOTAL_ entries", pagination: { first: "First", previous: "Previous", next: "Next", last: "Last" } }, length_menu: [10, 25, 50, 75, 100], no_data_text: "No rows found", page_size: 10, sort: { column: "test", order: "asc" }, show_length_menu: true, show_filter: true, show_pagination: true, show_info: true, show_first: true, show_last: true }, dynamic: false, records: [], total_record: 0, onChange: function onChange() {}, onPageChange: function onPageChange() {}, onRowClicked: function onRowClicked() {} }; exports.default = ReactDatatable;