diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..49d515ed9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,24 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: AllenFang + +--- + +**Describe the bug** +A clear and concise description of what the bug is. In addition, please search issues before you open a report to make sure there's no any duplicated report + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**codesandbox** +Please give a simple and minimal example on https://codesandbox.io so that we can reproduce it easily and handle it effectively diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..9ab483b61 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,23 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: AllenFang + +--- + +**Is this feature requested before?** +Please search issues to make sure to create feature which is never report yet. + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/i-have-a-question.md b/.github/ISSUE_TEMPLATE/i-have-a-question.md new file mode 100644 index 000000000..d05d43578 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/i-have-a-question.md @@ -0,0 +1,17 @@ +--- +name: I have a question +about: I have a question +title: '' +labels: '' +assignees: AllenFang + +--- + +**Question** +A clear and concise description of you question. In addition, please search issues before you open a question to make sure there's no any duplicated questions. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**codesandbox** +Please give a simple and minimal example on https://codesandbox.io so that we can reproduce it easily. diff --git a/README.md b/README.md index ca053501d..290d5ee78 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # react-bootstrap-table2 [![Build Status](https://travis-ci.org/react-bootstrap-table/react-bootstrap-table2.svg?branch=master)](https://travis-ci.org/react-bootstrap-table/react-bootstrap-table2) -Rebuilt of [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-table) +Rebuild of [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-table) > Note that `react-bootstrap-table2`'s npm module name is [**`react-bootstrap-table-next`**](https://www.npmjs.com/package/react-bootstrap-table-next) due to the name being already taken. diff --git a/docs/README.md b/docs/README.md index dc12d3aeb..9bc4ff181 100644 --- a/docs/README.md +++ b/docs/README.md @@ -21,6 +21,7 @@ * [classes](#classes) * [wrapperClasses](#wrapperClasses) * [headerClasses](#headerClasses) +* [headerWrapperClasses](#headerWrapperClasses) * [cellEdit](#cellEdit) * [selectRow](#selectRow) * [expandRow](#expandRow) @@ -28,19 +29,46 @@ * [rowClasses](#rowClasses) * [rowEvents](#rowEvents) * [hiddenRows](#hiddenRows) +* [sort](#sort) * [defaultSorted](#defaultSorted) * [defaultSortDirection](#defaultSortDirection) * [pagination](#pagination) * [filter](#filter) +* [filterPosition](filterPosition) * [onTableChange](#onTableChange) * [onDataSizeChange](#onDataSizeChange) ### keyField(**required**) - [String] -Tells `react-bootstrap-table2` which column is unique. +Tells `react-bootstrap-table2` which column of the data is unique. This should be the name of a property that is unique for each item in your dataset ### data(**required**) - [Array] Provides data for your table. It accepts a single Array object. +Each item in this array is an object that represents a row in the table. Each "Row" object should have a key-value pair for each column in the table, whose key matches that column's dataField value. + +For example, if your column definitions look like: + +```js +columns = [ + { dataField: 'id', text: 'Id' }, + { dataField: 'name', text: 'Name' }, + { dataField: 'animal', text: 'Animal' }, +] +``` + +Then your data might look like: + +```js +data = [ + { id: 1, name: 'George', animal: 'Monkey' } + { id: 2, name: 'Jeffrey', animal: 'Giraffe' } + { id: 3, name: 'Alice', animal: 'Giraffe' } + { id: 4, name: 'Alice', animal: 'Tiger' } +] +``` + +And your "keyField" would be `id` + ### columns(**required**) - [Object] Accepts a single Array object, please see [columns definition](./columns.md) for more detail. @@ -98,7 +126,14 @@ import overlayFactory from 'react-bootstrap-table2-overlay'; Actually, `react-bootstrap-table-overlay` is depends on [`react-loading-overlay`](https://github.com/derrickpelletier/react-loading-overlay) and `overlayFactory` just a factory function and you can pass any props which available for `react-loading-overlay`: ```js -overlay={ overlayFactory({ spinner: true, background: 'rgba(192,192,192,0.3)' }) } +overlay={ + overlayFactory({ + spinner: true, + styles: { + overlay: (base) => ({...base, background: 'rgba(255, 0, 0, 0.5)'}) + } + }) +} ``` ### caption - [String | Node] @@ -128,6 +163,9 @@ Customize class on the outer element which wrap up the `table` element. ### headerClasses - [String] Customize class on the header row(`tr`). +### headerWrapperClasses - [String] +Customize class on the `thead`. + ### cellEdit - [Object] Makes table cells editable, please see [cellEdit definition](./cell-edit.md) for more detail. @@ -191,6 +229,27 @@ const hiddenRows = [1, 4]; ``` +### sort - [Object] +Two cases you probably need to configure `sort` prop: + +#### Manage sorting state +You can give `dataField` and `order` to specify the sorting state in table, For example + +```js + +``` + +#### One-time sorting configuration +In earily version, we only can configure [`sortCaret`](./columns.md#sortCaret) and [`sortFunc` ](./columns.md#sortFunc) per column. But they are same in most of cases. +So here we give you a chance to just setup these prop in one time. + +```js + +``` + ### defaultSorted - [Array] `defaultSorted` accept an object array which allow you to define the default sort columns when first render. @@ -201,6 +260,8 @@ const defaultSorted = [{ }]; ``` +**Note**: Only the first column is sorted currently, see #1083. + ### defaultSortDirection - [String] Default sort direction when user click on header column at first time, available value is `asc` and `desc`. Default is `desc`. @@ -320,6 +381,9 @@ Following is a shape of `newState` } ``` +### filterPosition - [String] +Available value is `inline`, `top` and `bottom`, default is `inline`. This prop decide where `react-bootstrap-table` render column filter. + ### onDataSizeChange - [Function] This callback function will be called only when data size change by search/filter etc. This function have one argument which is an object contains below props: @@ -334,4 +398,4 @@ handleDataChange = ({ dataSize }) => { onDataSizeChange={ handleDataChange } .... /> -``` \ No newline at end of file +``` diff --git a/docs/columns.md b/docs/columns.md index 55a4003e6..1749b8916 100644 --- a/docs/columns.md +++ b/docs/columns.md @@ -11,7 +11,9 @@ Available properties in a column object: * [hidden](#hidden) * [formatter](#formatter) * [formatExtraData](#formatExtraData) +* [type](#type) * [sort](#sort) +* [sortValue](#sortValue) * [sortFunc](#sortFunc) * [sortCaret](#sortCaret) * [onSort](#onSort) @@ -48,6 +50,7 @@ Available properties in a column object: * [editorRenderer](#editorRenderer) * [filter](#filter) * [filterValue](#filterValue) +* [searchable](#searchable) * [csvType](#csvType) * [csvFormatter](#csvFormatter) * [csvText](#csvText) @@ -132,11 +135,49 @@ The third argument: `components` have following specified properties: ## column.formatExtraData - [Any] It's only used for [`column.formatter`](#formatter), you can define any value for it and will be passed as fourth argument for [`column.formatter`](#formatter) callback function. +## column.type - [String] +Specify the data type on column. Available value so far is `string`, `number`, `bool` and `date`. Default is `string`. +`column.type` can be used when you enable the cell editing and want to save your cell data with correct data type. + ## column.sort - [Bool] Enable the column sort via a `true` value given. +## column.sortValue - [Function] +`column.sortValue` only work when `column.sort` enabled. This prop allow you to replace the value when table sorting. + +For example, consider following data: + +```js +const types = ['Cloud Service', 'Message Service', 'Add Service', 'Edit Service', 'Money']; +const data = [{id: 1, type: 2}, {id: 2, type: 1}, {id: 3, type:0}]; +const columns = [{ + dataField: 'id', + text: 'Job ID' +}, { + dataField: 'type', + text: 'Job Type' + sort: true, + formatter: (cell, row) => types[cell] +}] +``` + +In above case, when user try to sort Job Type column which will sort the original value: 0, 1, 2 but we display the type name via [`column.formatter`](#formatter), which will lead confuse because we are sorting by type value instead of type name. So `sortValue` is a way for you to decide what kind of value should be adopted when sorting on a specify column: + +```js +const columns = [{ + dataField: 'id', + text: 'Job ID' +}, { + dataField: 'type', + text: 'Job Type' + sort: true, + formatter: (cell, row) => types[cell], + sortValue: (cell, row) => types[cell] // we use type name to sort. +}] +``` + ## column.sortFunc - [Function] -`column.sortFunc` only work when `column.sort` is enable. `sortFunc` allow you to define your sorting algorithm. This callback function accept six arguments: +`column.sortFunc` only work when `column.sort` enabled. `sortFunc` allow you to define your sorting algorithm. This callback function accept six arguments: ```js { @@ -396,6 +437,7 @@ You can assign any [HTML Event](https://www.w3schools.com/tags/ref_eventattribut * onMouseEnter * onMouseLeave * onContextMenu +* onAuxClick ```js { @@ -415,7 +457,7 @@ If the events is not listed above, the callback function will only pass the `eve { // omit... headerEvents: { - onClick: e => { ... } + onClick: (e, column, columnIndex) => { ... } } } ``` @@ -553,6 +595,7 @@ This prop also accept a function: * `column` * `columnIndex` +* `props`: It's an object and contain `text` property only. ## column.footerClasses - [String | Function] It's similar to [`column.classes`](#classes), `footerClasses` is available to have customized class on table footer column: @@ -625,7 +668,7 @@ It's also available to custom via a callback function: { // omit... footerEvents: { - onClick: e => { ... } + onClick: (e, column, columnIndex) => { ... } } } ``` @@ -912,6 +955,9 @@ A final `String` value you want to be filtered. } ``` +## column.searchable - [Boolean] +Default the column is searchable. Give `false` to disable search functionality on specified column. + ## column.csvType - [Object] Default is `String`. Currently, the available value is `String` and `Number`. If `Number` assigned, the cell value will not wrapped with double quote. diff --git a/docs/row-expand.md b/docs/row-expand.md index 08198fad7..a4b49d528 100644 --- a/docs/row-expand.md +++ b/docs/row-expand.md @@ -18,6 +18,8 @@ * [expandColumnPosition](#expandColumnPosition) * [expandColumnRenderer](#expandColumnRenderer) * [expandHeaderColumnRenderer](#expandHeaderColumnRenderer) +* [className](#className) +* [parentClassName](#parentClassName) ### expandRow.renderer - [Function] @@ -25,12 +27,13 @@ Specify the content of expand row, `react-bootstrap-table2` will pass a row obje #### values * **row** +* **rowIndex** #### examples ```js const expandRow = { - renderer: row => ( + renderer: (row, rowIndex) => (

{ `This Expand row is belong to rowKey ${row.id}` }

You can render anything here, also you can add additional data on every row object

@@ -165,3 +168,45 @@ const expandRow = { expandColumnPosition: 'right' }; ``` + +### expandRow.className - [String | Function] +Apply the custom class name on the expanding row. For example: + +```js +const expandRow = { + renderer: (row) => ..., + className: 'foo' +}; +``` +following usage is more flexible way for customing the class name: + +```js +const expandRow = { + renderer: (row) => ..., + className: (isExpanded, row, rowIndex) => { + if (rowIndex > 2) return 'foo'; + return 'bar'; + } +}; +``` + +### expandRow.parentClassName - [String | Function] +Apply the custom class name on parent row of expanded row. For example: + +```js +const expandRow = { + renderer: (row) => ..., + parentClassName: 'foo' +}; +``` +Below case is more flexible way to custom the class name: + +```js +const expandRow = { + renderer: (row) => ..., + parentClassName: (isExpanded, row, rowIndex) => { + if (rowIndex > 2) return 'foo'; + return 'bar'; + } +}; +``` \ No newline at end of file diff --git a/docs/row-selection.md b/docs/row-selection.md index af2d16a5f..dce1f9f07 100644 --- a/docs/row-selection.md +++ b/docs/row-selection.md @@ -1,6 +1,6 @@ # Row selection -`react-bootstrap-table2` supports the row selection feature. By passing prop `selectRow` to enable row selection. When you enable this feature, `react-bootstrap-table2` will prepend a new selection column. +`react-bootstrap-table2` supports the row selection feature. By passing prop `selectRow` to enable row selection. When you enable this feature, `react-bootstrap-table2` will prepend a new selection column. ## Required * [mode (**required**)](#mode) @@ -11,6 +11,8 @@ * [classes)](#classes) * [bgColor](#bgColor) * [nonSelectable)](#nonSelectable) +* [nonSelectableStyle](#nonSelectableStyle) +* [nonSelectableClasses](#nonSelectableClasses) * [clickToSelect)](#clickToSelect) * [clickToExpand)](#clickToExpand) * [clickToEdit](#clickToEdit) @@ -139,6 +141,54 @@ const selectRow = { }; ``` +### selectRow.nonSelectableStyle - [Object | Function] +This prop allow you to customize the non selectable rows. `selectRow.nonSelectableStyle` accepts an style object +and a callback function for more flexible customization. + +### Style Object + +```js +const selectRow = { + mode: 'checkbox', + nonSelectable: [1, 3 ,5], + nonSelectableStyle: { backgroundColor: 'gray' } +}; +``` + +### Callback Function + +```js +const selectRow = { + mode: 'checkbox', + nonSelectable: [1, 3 ,5], + nonSelectableStyle: (row, rowIndex) => { return ...; } +}; +``` + +### selectRow.nonSelectableClasses - [String | Function] +This prop allow you to set a custom class for the non selectable rows, or use a callback function for more +flexible customization + +### String + +```js +const selectRow = { + mode: 'checkbox', + nonSelectable: [1, 3 ,5], + nonSelectableClasses: 'my-class' +}; +``` + +### Callback Function + +```js +const selectRow = { + mode: 'checkbox', + nonSelectable: [1, 3 ,5], + nonSelectableClasses: (row, rowIndex) => { return ...; } +}; +``` + ### selectRow.clickToSelect - [Bool] Allow user to select row by clicking on the row. @@ -149,7 +199,7 @@ const selectRow = { }; ``` -> Note: When you also enable [cellEdit](./cell-edit.md), the `selectRow.clickToSelect` will deactivate the functionality of cell editing +> Note: When you also enable [cellEdit](./cell-edit.md), the `selectRow.clickToSelect` will deactivate the functionality of cell editing > If you want to click on row to select row and edit cell simultaneously, you are suppose to enable [`selectRow.clickToEdit`](#clickToEdit) ### selectRow.clickToExpand - [Bool] @@ -307,7 +357,7 @@ const selectRow = { mode: 'checkbox', onSelectAll: (isSelect, rows, e) => { if (isSelect && SOME_CONDITION) { - return [1, 3, 4]; // finally, key 1, 3, 4 will being selected + return [1, 3, 4]; // finally, key 1, 3, 4 will being selected } } }; diff --git a/package.json b/package.json index 37859fdbd..2f5a73525 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "webpack-dev-server": "2.7.1" }, "dependencies": { - "classnames": "2.2.5", + "classnames": "^2.2.5", "prop-types": "15.5.10", "react": "16.4.0", "react-dom": "16.4.0", diff --git a/packages/react-bootstrap-table2-editor/README.md b/packages/react-bootstrap-table2-editor/README.md index b4e6b99aa..cda2e0a59 100644 --- a/packages/react-bootstrap-table2-editor/README.md +++ b/packages/react-bootstrap-table2-editor/README.md @@ -140,7 +140,7 @@ const columns = [ text: 'Job Type', editor: { type: Type.SELECT, - getOptions: () => [.....] + getOptions: (setOptions, { row, column }) => [.....] } }]; @@ -152,7 +152,7 @@ const columns = [ text: 'Job Type', editor: { type: Type.SELECT, - getOptions: (setOptions) => { + getOptions: (setOptions, { row, column }) => { setTimeout(() => setOptions([...]), 1500); } } diff --git a/packages/react-bootstrap-table2-editor/package.json b/packages/react-bootstrap-table2-editor/package.json index b8171170b..8eb8e1460 100644 --- a/packages/react-bootstrap-table2-editor/package.json +++ b/packages/react-bootstrap-table2-editor/package.json @@ -1,6 +1,6 @@ { "name": "react-bootstrap-table2-editor", - "version": "1.2.4", + "version": "1.4.0", "description": "it's the editor addon for react-bootstrap-table2", "main": "./lib/index.js", "scripts": { diff --git a/packages/react-bootstrap-table2-editor/src/context.js b/packages/react-bootstrap-table2-editor/src/context.js index e9317e2f1..30f5e6ae0 100644 --- a/packages/react-bootstrap-table2-editor/src/context.js +++ b/packages/react-bootstrap-table2-editor/src/context.js @@ -1,5 +1,8 @@ +/* eslint disable-next-line: 0 */ /* eslint react/prop-types: 0 */ /* eslint react/require-default-props: 0 */ +/* eslint camelcase: 0 */ +/* eslint react/no-unused-prop-types: 0 */ import React from 'react'; import PropTypes from 'prop-types'; import { CLICK_TO_CELL_EDIT, DBCLICK_TO_CELL_EDIT } from './const'; @@ -43,7 +46,7 @@ export default ( }; } - componentWillReceiveProps(nextProps) { + UNSAFE_componentWillReceiveProps(nextProps) { if (nextProps.cellEdit && isRemoteCellEdit()) { if (nextProps.cellEdit.options.errorMessage) { this.setState(() => ({ @@ -56,12 +59,13 @@ export default ( } handleCellUpdate(row, column, newValue) { + const newValueWithType = dataOperator.typeConvert(column.type, newValue); const { cellEdit } = this.props; const { beforeSaveCell } = cellEdit.options; const oldValue = _.get(row, column.dataField); const beforeSaveCellDone = (result = true) => { if (result) { - this.doUpdate(row, column, newValue); + this.doUpdate(row, column, newValueWithType); } else { this.escapeEditing(); } @@ -69,7 +73,7 @@ export default ( if (_.isFunction(beforeSaveCell)) { const result = beforeSaveCell( oldValue, - newValue, + newValueWithType, row, column, beforeSaveCellDone @@ -78,7 +82,7 @@ export default ( return; } } - this.doUpdate(row, column, newValue); + this.doUpdate(row, column, newValueWithType); } doUpdate(row, column, newValue) { diff --git a/packages/react-bootstrap-table2-editor/src/dropdown-editor.js b/packages/react-bootstrap-table2-editor/src/dropdown-editor.js index a54bc4d62..b019e2ea6 100644 --- a/packages/react-bootstrap-table2-editor/src/dropdown-editor.js +++ b/packages/react-bootstrap-table2-editor/src/dropdown-editor.js @@ -8,7 +8,13 @@ class DropDownEditor extends Component { super(props); let options = props.options; if (props.getOptions) { - options = props.getOptions(this.setOptions.bind(this)) || []; + options = props.getOptions( + this.setOptions.bind(this), + { + row: props.row, + column: props.column + } + ) || []; } this.state = { options }; } @@ -54,6 +60,8 @@ class DropDownEditor extends Component { } DropDownEditor.propTypes = { + row: PropTypes.object.isRequired, + column: PropTypes.object.isRequired, defaultValue: PropTypes.oneOfType([ PropTypes.string, PropTypes.number diff --git a/packages/react-bootstrap-table2-editor/src/editing-cell.js b/packages/react-bootstrap-table2-editor/src/editing-cell.js index 7c693b127..e72999852 100644 --- a/packages/react-bootstrap-table2-editor/src/editing-cell.js +++ b/packages/react-bootstrap-table2-editor/src/editing-cell.js @@ -2,6 +2,7 @@ /* eslint no-return-assign: 0 */ /* eslint class-methods-use-this: 0 */ /* eslint jsx-a11y/no-noninteractive-element-interactions: 0 */ +/* eslint camelcase: 0 */ import React, { Component } from 'react'; import cs from 'classnames'; import PropTypes from 'prop-types'; @@ -51,7 +52,11 @@ export default (_, onStartEdit) => }; } - componentWillReceiveProps({ message }) { + componentWillUnmount() { + this.clearTimer(); + } + + UNSAFE_componentWillReceiveProps({ message }) { if (_.isDefined(message)) { this.createTimer(); this.setState(() => ({ @@ -60,10 +65,6 @@ export default (_, onStartEdit) => } } - componentWillUnmount() { - this.clearTimer(); - } - clearTimer() { if (this.indicatorTimer) { clearTimeout(this.indicatorTimer); @@ -201,7 +202,7 @@ export default (_, onStartEdit) => if (_.isFunction(column.editorRenderer)) { editor = column.editorRenderer(editorProps, value, row, column, rowIndex, columnIndex); } else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.SELECT) { - editor = ; + editor = ; } else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.TEXTAREA) { editor = ; } else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.CHECKBOX) { diff --git a/packages/react-bootstrap-table2-editor/test/context.test.js b/packages/react-bootstrap-table2-editor/test/context.test.js index 57b56bfd9..65e9d2ced 100644 --- a/packages/react-bootstrap-table2-editor/test/context.test.js +++ b/packages/react-bootstrap-table2-editor/test/context.test.js @@ -117,7 +117,7 @@ describe('CellEditContext', () => { wrapper = shallow(shallowContext()); wrapper.setState(initialState); wrapper.render(); - wrapper.instance().componentWillReceiveProps({}); + wrapper.instance().UNSAFE_componentWillReceiveProps({}); }); it('should not set state.message', () => { @@ -138,7 +138,7 @@ describe('CellEditContext', () => { wrapper = shallow(shallowContext()); wrapper.setState(initialState); wrapper.render(); - wrapper.instance().componentWillReceiveProps({ + wrapper.instance().UNSAFE_componentWillReceiveProps({ cellEdit: cellEditFactory(defaultCellEdit) }); }); @@ -164,7 +164,7 @@ describe('CellEditContext', () => { wrapper = shallow(shallowContext(defaultCellEdit, true)); wrapper.setState(initialState); wrapper.render(); - wrapper.instance().componentWillReceiveProps({ + wrapper.instance().UNSAFE_componentWillReceiveProps({ cellEdit: cellEditFactory({ ...defaultCellEdit, errorMessage: message @@ -190,7 +190,7 @@ describe('CellEditContext', () => { beforeEach(() => { wrapper = shallow(shallowContext(defaultCellEdit, true)); wrapper.setState(initialState); - wrapper.instance().componentWillReceiveProps({ + wrapper.instance().UNSAFE_componentWillReceiveProps({ cellEdit: cellEditFactory({ ...defaultCellEdit }) }); wrapper.update(); diff --git a/packages/react-bootstrap-table2-example/examples/basic/customized-id-classes.js b/packages/react-bootstrap-table2-example/examples/basic/customized-id-classes.js index fae4bf723..63ec718d9 100644 --- a/packages/react-bootstrap-table2-example/examples/basic/customized-id-classes.js +++ b/packages/react-bootstrap-table2-example/examples/basic/customized-id-classes.js @@ -33,6 +33,8 @@ const columns = [{ + + `; @@ -44,6 +46,12 @@ export default () => (

Customized table className

+

Customized thead className

+ + +

Customized tbody className

+ +

Customized wrapper className

diff --git a/packages/react-bootstrap-table2-example/examples/bootstrap4/caption-table.js b/packages/react-bootstrap-table2-example/examples/bootstrap4/caption-table.js new file mode 100644 index 000000000..1c23a3c0f --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/bootstrap4/caption-table.js @@ -0,0 +1,49 @@ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const products = productsGenerator(); + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const CaptionElement = () =>

Component as Header

; + + + +} columns={ columns } /> +`; + +const Caption = () =>

Component as Header

; + +export default () => ( +
+ + } columns={ columns } /> + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/cell-edit/cell-edit-with-data-type.js b/packages/react-bootstrap-table2-example/examples/cell-edit/cell-edit-with-data-type.js new file mode 100644 index 000000000..28a064bd6 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/cell-edit/cell-edit-with-data-type.js @@ -0,0 +1,123 @@ +/* eslint prefer-template: 0 */ +import React from 'react'; +import BootstrapTable from 'react-bootstrap-table-next'; +import cellEditFactory, { Type } from 'react-bootstrap-table2-editor'; +import Code from 'components/common/code-block'; +import { stockGenerator } from 'utils/common'; + +const products = stockGenerator(); + +const columns = [{ + dataField: 'id', + text: 'Stock ID' +}, { + dataField: 'name', + text: 'Stock Name' +}, { + dataField: 'price', + text: 'Price', + type: 'number' +}, { + dataField: 'visible', + text: 'Visible?', + type: 'bool', + editor: { + type: Type.CHECKBOX, + value: 'true:false' + } +}, { + dataField: 'inStockDate', + text: 'Stock Date', + type: 'date', + formatter: (cell) => { + let dateObj = cell; + if (typeof cell !== 'object') { + dateObj = new Date(cell); + } + return `${('0' + dateObj.getUTCDate()).slice(-2)}/${('0' + (dateObj.getUTCMonth() + 1)).slice(-2)}/${dateObj.getUTCFullYear()}`; + }, + editor: { + type: Type.DATE + } +}]; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; +import cellEditFactory from 'react-bootstrap-table2-editor'; + +const columns = [{ + dataField: 'id', + text: 'Stock ID' +}, { + dataField: 'name', + text: 'Stock Name' +}, { + dataField: 'price', + text: 'Price', + type: 'number' +}, { + dataField: 'visible', + text: 'Visible?', + type: 'bool', + editor: { + type: Type.CHECKBOX, + value: 'true:false' + } +}, { + dataField: 'inStockDate', + text: 'Stock Date', + type: 'date', + formatter: (cell) => { + let dateObj = cell; + if (typeof cell !== 'object') { + dateObj = new Date(cell); + } + return \`$\{('0' + dateObj.getUTCDate()).slice(-2)}/$\{('0' + (dateObj.getUTCMonth() + 1)).slice(-2)}/$\{dateObj.getUTCFullYear()}\`; + }, + editor: { + type: Type.DATE + } +}]; + +function afterSaveCell(oldValue, newValue) { + console.log('--after save cell--'); + console.log('New Value was apply as'); + console.log(newValue); + console.log(\`and the type is $\{typeof newValue}\`); +} + + +`; + +function afterSaveCell(oldValue, newValue) { + console.log('--after save cell--'); + console.log('New Value was apply as'); + console.log(newValue); + console.log(`and the type is ${typeof newValue}`); +} + +export default () => ( +
+

Save Cell Value with Specified Data Type

+ + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/cell-edit/dropdown-editor-with-dynamic-options-table.js b/packages/react-bootstrap-table2-example/examples/cell-edit/dropdown-editor-with-dynamic-options-table.js index 715346ba4..02c822b0d 100644 --- a/packages/react-bootstrap-table2-example/examples/cell-edit/dropdown-editor-with-dynamic-options-table.js +++ b/packages/react-bootstrap-table2-example/examples/cell-edit/dropdown-editor-with-dynamic-options-table.js @@ -1,3 +1,4 @@ +/* eslint no-console: 0 */ /* eslint react/prefer-stateless-function: 0 */ import React from 'react'; @@ -25,22 +26,26 @@ const columns = [{ text: 'Job Type1', editor: { type: Type.SELECT, - getOptions: () => [{ - value: 'A', - label: 'A' - }, { - value: 'B', - label: 'B' - }, { - value: 'C', - label: 'C' - }, { - value: 'D', - label: 'D' - }, { - value: 'E', - label: 'E' - }] + getOptions: (setOptions, { row, column }) => { + console.log(`current editing row id: ${row.id}`); + console.log(`current editing column: ${column.dataField}`); + return [{ + value: 'A', + label: 'A' + }, { + value: 'B', + label: 'B' + }, { + value: 'C', + label: 'C' + }, { + value: 'D', + label: 'D' + }, { + value: 'E', + label: 'E' + }]; + } } }, { dataField: 'type2', @@ -88,22 +93,26 @@ const columns = [{ text: 'Job Type1', editor: { type: Type.SELECT, - getOptions: () => [{ - value: 'A', - label: 'A' - }, { - value: 'B', - label: 'B' - }, { - value: 'C', - label: 'C' - }, { - value: 'D', - label: 'D' - }, { - value: 'E', - label: 'E' - }] + getOptions: (setOptions, { row, column }) => { + console.log(\`current editing row id: $\{row.id}\`); + console.log(\`current editing column: $\{column.dataField}\`); + return [{ + value: 'A', + label: 'A' + }, { + value: 'B', + label: 'B' + }, { + value: 'C', + label: 'C' + }, { + value: 'D', + label: 'D' + }, { + value: 'E', + label: 'E' + }]; + } } }, { dataField: 'type2', diff --git a/packages/react-bootstrap-table2-example/examples/column-filter/clear-all-filters.js b/packages/react-bootstrap-table2-example/examples/column-filter/clear-all-filters.js index 3e2a25bfa..c15f560a8 100644 --- a/packages/react-bootstrap-table2-example/examples/column-filter/clear-all-filters.js +++ b/packages/react-bootstrap-table2-example/examples/column-filter/clear-all-filters.js @@ -1,13 +1,20 @@ import React from 'react'; import BootstrapTable from 'react-bootstrap-table-next'; -import filterFactory, { textFilter, dateFilter } from 'react-bootstrap-table2-filter'; +import filterFactory, { textFilter, dateFilter, selectFilter } from 'react-bootstrap-table2-filter'; import Code from 'components/common/code-block'; import { stockGenerator } from 'utils/common'; const products = stockGenerator(8); +const selectOptions = { + 0: 'good', + 1: 'Bad', + 2: 'unknown' +}; + let nameFilter; let priceFilter; +let qualityFilter; let stockDateFilter; const columns = [{ @@ -19,7 +26,19 @@ const columns = [{ filter: textFilter({ getFilter: (filter) => { nameFilter = filter; - } + }, + onFilter: filterVal => console.log(`Filter product name ${filterVal}`) + }) +}, { + dataField: 'quality', + text: 'Product Quailty', + formatter: cell => selectOptions[cell], + filter: selectFilter({ + options: selectOptions, + getFilter: (filter) => { + qualityFilter = filter; + }, + onFilter: filterVal => console.log(`Filter quality ${filterVal}`) }) }, { dataField: 'price', @@ -27,7 +46,8 @@ const columns = [{ filter: textFilter({ getFilter: (filter) => { priceFilter = filter; - } + }, + onFilter: filterVal => console.log(`Filter Price: ${filterVal}`) }) }, { dataField: 'inStockDate', @@ -36,13 +56,15 @@ const columns = [{ filter: dateFilter({ getFilter: (filter) => { stockDateFilter = filter; - } + }, + onFilter: filterVal => console.log(`Filter date: ${filterVal}`) }) }]; const handleClick = () => { nameFilter(''); priceFilter(''); + qualityFilter(''); stockDateFilter(); }; diff --git a/packages/react-bootstrap-table2-example/examples/column-filter/custom-filter-logic.js b/packages/react-bootstrap-table2-example/examples/column-filter/custom-filter-logic.js index 906d9d0f8..a861f5af1 100644 --- a/packages/react-bootstrap-table2-example/examples/column-filter/custom-filter-logic.js +++ b/packages/react-bootstrap-table2-example/examples/column-filter/custom-filter-logic.js @@ -12,8 +12,12 @@ import BootstrapTable from 'react-bootstrap-table-next'; import filterFactory, { textFilter } from 'react-bootstrap-table2-filter'; class Table extends React.Component { - filterByPrice = filterVal => - products.filter(product => product.price == filterVal); + filterByPrice = (filterVal, data) => { + if (filterVal) { + return data.filter(product => product.price == filterVal); + } + return data; + } render() { const columns = [{ @@ -46,8 +50,12 @@ class Table extends React.Component { `; export default class Table extends React.Component { - filterByPrice = filterVal => - products.filter(product => product.price == filterVal); + filterByPrice = (filterVal, data) => { + if (filterVal) { + return data.filter(product => product.price == filterVal); + } + return data; + } render() { const columns = [{ @@ -67,7 +75,7 @@ export default class Table extends React.Component { return (
-

Implement a eq filter on product price column

+

Implement a eq price filter

+function afterFilter(newResult, newFilters) { + console.log(newResult); + console.log(newFilters); +} + + `; +function afterFilter(newResult, newFilters) { + console.log(newResult); + console.log(newFilters); +} + export default () => (
{ sourceCode }
diff --git a/packages/react-bootstrap-table2-example/examples/column-filter/filter-position.js b/packages/react-bootstrap-table2-example/examples/column-filter/filter-position.js new file mode 100644 index 000000000..661ef3dba --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/column-filter/filter-position.js @@ -0,0 +1,114 @@ +import React from 'react'; +import BootstrapTable from 'react-bootstrap-table-next'; +import filterFactory, { textFilter } from 'react-bootstrap-table2-filter'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const products = productsGenerator(8); + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name', + filter: textFilter() +}, { + dataField: 'price', + text: 'Product Price', + filter: textFilter() +}]; + +const sourceCode1 = `\ +import BootstrapTable from 'react-bootstrap-table-next'; +import filterFactory, { textFilter } from 'react-bootstrap-table2-filter'; + +const columns = [{ + dataField: 'id', + text: 'Product ID', +}, { + dataField: 'name', + text: 'Product Name', + filter: textFilter() +}, { + dataField: 'price', + text: 'Product Price', + filter: textFilter() +}]; + + +`; + +const sourceCode2 = `\ +import BootstrapTable from 'react-bootstrap-table-next'; +import filterFactory, { textFilter } from 'react-bootstrap-table2-filter'; + +const columns = [{ + dataField: 'id', + text: 'Product ID', +}, { + dataField: 'name', + text: 'Product Name', + filter: textFilter() +}, { + dataField: 'price', + text: 'Product Price', + filter: textFilter() +}]; + + +`; + +const selectRow = { + mode: 'checkbox', + clickToSelect: true +}; + +const expandRow = { + renderer: row => ( +
+

{ `This Expand row is belong to rowKey ${row.id}` }

+

You can render anything here, also you can add additional data on every row object

+

expandRow.renderer callback will pass the origin row object to you

+
+ ), + showExpandColumn: true, + expandColumnPosition: 'right' +}; + +export default () => ( +
+ + { sourceCode1 } + + { sourceCode2 } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/column-filter/select-filter-option-type.js b/packages/react-bootstrap-table2-example/examples/column-filter/select-filter-option-type.js new file mode 100644 index 000000000..5591d4a86 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/column-filter/select-filter-option-type.js @@ -0,0 +1,150 @@ +import React from 'react'; +import BootstrapTable from 'react-bootstrap-table-next'; +import filterFactory, { selectFilter } from 'react-bootstrap-table2-filter'; +import Code from 'components/common/code-block'; +import { productsQualityGenerator } from 'utils/common'; + +const products = productsQualityGenerator(6); + +const selectOptions = { + 0: 'good', + 1: 'Bad', + 2: 'unknown' +}; + +const selectOptionsArr = [{ + value: 0, + label: 'good' +}, { + value: 1, + label: 'Bad' +}, { + value: 2, + label: 'unknown' +}]; + +const columns1 = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'quality', + text: 'Product Quailty', + formatter: cell => selectOptions[cell], + filter: selectFilter({ + options: selectOptions + }) +}]; + +const columns2 = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'quality', + text: 'Product Quailty', + formatter: cell => selectOptionsArr.filter(opt => opt.value === cell)[0].label || '', + filter: selectFilter({ + options: selectOptionsArr + }) +}]; + +const columns3 = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'quality', + text: 'Product Quailty', + formatter: cell => selectOptionsArr.filter(opt => opt.value === cell)[0].label || '', + filter: selectFilter({ + options: () => selectOptionsArr + }) +}]; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; +import filterFactory, { selectFilter } from 'react-bootstrap-table2-filter'; + +// Object map options +const selectOptions = { + 0: 'good', + 1: 'Bad', + 2: 'unknown' +}; + +// Array options +const selectOptionsArr = [{ + value: 0, + label: 'good' +}, { + value: 1, + label: 'Bad' +}, { + value: 2, + label: 'unknown' +}]; + +const columns1 = [..., { + dataField: 'quality', + text: 'Product Quailty', + formatter: cell => selectOptions[cell], + filter: selectFilter({ + options: selectOptions + }) +}]; + + +const columns2 = [..., { + dataField: 'quality', + text: 'Product Quailty', + formatter: cell => selectOptionsArr.filter(opt => opt.value === cell)[0].label || '', + filter: selectFilter({ + options: selectOptionsArr + }) +}]; + + +const columns3 = [..., { + dataField: 'quality', + text: 'Product Quailty', + formatter: cell => selectOptionsArr.filter(opt => opt.value === cell)[0].label || '', + filter: selectFilter({ + options: () => selectOptionsArr + }) +}]; + +`; + +export default () => ( +
+

Options as an object

+ +

Options as an array

+ +

Options as a function which return an array

+ + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/column-filter/text-filter.js b/packages/react-bootstrap-table2-example/examples/column-filter/text-filter.js index 19eab4702..58dc30828 100644 --- a/packages/react-bootstrap-table2-example/examples/column-filter/text-filter.js +++ b/packages/react-bootstrap-table2-example/examples/column-filter/text-filter.js @@ -8,14 +8,19 @@ const products = productsGenerator(8); const columns = [{ dataField: 'id', - text: 'Product ID' + text: 'Product ID', + footer: 'hello' }, { dataField: 'name', text: 'Product Name', - filter: textFilter() + footer: 'hello', + filter: textFilter({ + id: 'identify' + }) }, { dataField: 'price', text: 'Product Price', + footer: 'hello', filter: textFilter() }]; @@ -39,6 +44,11 @@ const columns = [{ `; +const selectRow = { + mode: 'checkbox', + clickToSelect: true +}; + export default () => (
( data={ products } columns={ columns } filter={ filterFactory() } + selectRow={ selectRow } /> { sourceCode }
diff --git a/packages/react-bootstrap-table2-example/examples/column-toggle/column-toggle-with-filter.js b/packages/react-bootstrap-table2-example/examples/column-toggle/column-toggle-with-filter.js new file mode 100644 index 000000000..e67541d8a --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/column-toggle/column-toggle-with-filter.js @@ -0,0 +1,94 @@ +/* eslint react/prop-types: 0 */ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import filterFactory, { textFilter } from 'react-bootstrap-table2-filter'; +import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const { ToggleList } = ColumnToggle; +const products = productsGenerator(); + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name', + sort: true, + filter: textFilter() +}, { + dataField: 'price', + text: 'Product Price', + sort: true, + filter: textFilter() +}]; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; +import filterFactory, { textFilter } from 'react-bootstrap-table2-filter'; +import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit'; + +const { ToggleList } = ColumnToggle; +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name', + sort: true, + filter: textFilter() +}, { + dataField: 'price', + text: 'Product Price', + sort: true, + filter: textFilter() +}]; + + + { + props => ( +
+ +
+ +
+ ) + } +
+`; + +export default () => ( +
+

Table will keep the filter/sort state when column toggle

+ + { + props => ( +
+ +
+ +
+ ) + } +
+ { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/csv/custom-csv.js b/packages/react-bootstrap-table2-example/examples/csv/custom-csv.js index a78d8b064..1fe5e9b40 100644 --- a/packages/react-bootstrap-table2-example/examples/csv/custom-csv.js +++ b/packages/react-bootstrap-table2-example/examples/csv/custom-csv.js @@ -40,7 +40,13 @@ const columns = [{ keyField="id" data={ products } columns={ columns } - exportCSV + exportCSV={ { + fileName: 'custom.csv', + separator: '|', + ignoreHeader: true, + noAutoBOM: false, + blobType: 'text/csv;charset=ansi' + } } > { props => ( @@ -64,7 +70,8 @@ export default () => ( fileName: 'custom.csv', separator: '|', ignoreHeader: true, - noAutoBOM: false + noAutoBOM: false, + blobType: 'text/csv;charset=ansi' } } > { diff --git a/packages/react-bootstrap-table2-example/examples/csv/export-custom-data.js b/packages/react-bootstrap-table2-example/examples/csv/export-custom-data.js index 50da9b782..929a9a298 100644 --- a/packages/react-bootstrap-table2-example/examples/csv/export-custom-data.js +++ b/packages/react-bootstrap-table2-example/examples/csv/export-custom-data.js @@ -36,11 +36,12 @@ const columns = [{ const MyExportCSV = (props) => { const handleClick = () => { - props.onExport(); + // passing my custom data + props.onExport(products.filter(r => r.id > 2)); }; return (
- +
); }; diff --git a/packages/react-bootstrap-table2-example/examples/csv/export-footer.js b/packages/react-bootstrap-table2-example/examples/csv/export-footer.js new file mode 100644 index 000000000..25f9dbcc5 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/csv/export-footer.js @@ -0,0 +1,88 @@ +/* eslint react/prop-types: 0 */ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import ToolkitProvider, { CSVExport } from 'react-bootstrap-table2-toolkit'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const { ExportCSVButton } = CSVExport; +const products = productsGenerator(); + +const columns = [{ + dataField: 'id', + text: 'Product ID', + footer: 'Footer 1' +}, { + dataField: 'name', + text: 'Product Name', + footer: '', + footerFormatter: column => column.text +}, { + dataField: 'price', + text: 'Product Price', + footer: columnData => columnData.reduce((acc, item) => acc + item, 0) +}]; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; +import ToolkitProvider, { CSVExport } from 'react-bootstrap-table2-toolkit'; + +const { ExportCSVButton } = CSVExport; +const columns = [{ + dataField: 'id', + text: 'Product ID', + footer: 'Footer 1' +}, { + dataField: 'name', + text: 'Product Name', + footer: 'Footer 2' +}, { + dataField: 'price', + text: 'Product Price', + footer: 'Footer 3' +}]; + + + { + props => ( +
+ Export CSV!! +
+ +
+ ) + } +
+`; + +export default () => ( +
+ + { + props => ( +
+ Export CSV!! +
+ +
+ ) + } +
+ { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/footer/column-event-table.js b/packages/react-bootstrap-table2-example/examples/footer/column-event-table.js index 6837eee0f..943c680fe 100644 --- a/packages/react-bootstrap-table2-example/examples/footer/column-event-table.js +++ b/packages/react-bootstrap-table2-example/examples/footer/column-event-table.js @@ -12,7 +12,7 @@ const columns = [{ dataField: 'id', text: 'Product ID', footerEvents: { - onClick: () => alert('Click on Product ID footer column') + onClick: (e, column, columnIndex) => alert(`Click on Product ID header column, columnIndex: ${columnIndex}`) }, footer: 'Footer 1' }, { @@ -32,7 +32,7 @@ const columns = [{ dataField: 'id', text: 'Product ID', footerEvents: { - onClick: () => alert('Click on Product ID footer column') + onClick: (e, column, columnIndex) => alert('Click on Product ID footer column') }, footer: 'Footer 1' }, { diff --git a/packages/react-bootstrap-table2-example/examples/footer/column-format-table.js b/packages/react-bootstrap-table2-example/examples/footer/column-format-table.js index 26fbbc08b..ccd85bfd7 100644 --- a/packages/react-bootstrap-table2-example/examples/footer/column-format-table.js +++ b/packages/react-bootstrap-table2-example/examples/footer/column-format-table.js @@ -7,7 +7,7 @@ import { productsGenerator } from 'utils/common'; const products = productsGenerator(); -function priceFormatter(column, colIndex) { +function priceFormatter(column, colIndex, { text }) { return (
$$ {column.text} $$ @@ -37,7 +37,7 @@ const columns = [ const sourceCode = `\ import BootstrapTable from 'react-bootstrap-table-next'; -function priceFormatter(column, colIndex) { +function priceFormatter(column, colIndex, { text }) { return (
$$ { column.text } $$
); diff --git a/packages/react-bootstrap-table2-example/examples/header-columns/column-event-table.js b/packages/react-bootstrap-table2-example/examples/header-columns/column-event-table.js index d4394a7a0..3312b39b5 100644 --- a/packages/react-bootstrap-table2-example/examples/header-columns/column-event-table.js +++ b/packages/react-bootstrap-table2-example/examples/header-columns/column-event-table.js @@ -12,7 +12,7 @@ const columns = [{ dataField: 'id', text: 'Product ID', headerEvents: { - onClick: () => alert('Click on Product ID header column') + onClick: (e, column, columnIndex) => alert(`Click on Product ID header column, columnIndex: ${columnIndex}`) } }, { dataField: 'name', @@ -29,7 +29,7 @@ const columns = [{ dataField: 'id', text: 'Product ID', headerEvents: { - onClick: () => alert('Click on Product ID header column') + onClick: (e, column, columnIndex) => alert('Click on Product ID header column') } }, { dataField: 'name', diff --git a/packages/react-bootstrap-table2-example/examples/loading-overlay/table-overlay.js b/packages/react-bootstrap-table2-example/examples/loading-overlay/table-overlay.js index efd296cc8..13ce1b120 100644 --- a/packages/react-bootstrap-table2-example/examples/loading-overlay/table-overlay.js +++ b/packages/react-bootstrap-table2-example/examples/loading-overlay/table-overlay.js @@ -36,7 +36,7 @@ const RemotePagination = ({ loading, data, page, sizePerPage, onTableChange, tot columns={ columns } pagination={ paginationFactory({ page, sizePerPage, totalSize }) } onTableChange={ onTableChange } - overlay={ overlayFactory({ spinner: true, background: 'rgba(192,192,192,0.3)' }) } + overlay={ overlayFactory({ spinner: true, styles: { overlay: (base) => ({...base, background: 'rgba(255, 0, 0, 0.5)'}) } }) } /> { sourceCode }
@@ -101,7 +101,12 @@ const RemotePagination = ({ loading, data, page, sizePerPage, onTableChange, tot columns={ columns } pagination={ paginationFactory({ page, sizePerPage, totalSize }) } onTableChange={ onTableChange } - overlay={ overlayFactory({ spinner: true, background: 'rgba(192,192,192,0.3)' }) } + overlay={ + overlayFactory({ + spinner: true, + styles: { overlay: base => ({ ...base, background: 'rgba(255, 0, 0, 0.5)' }) } + }) + } /> { sourceCode }
diff --git a/packages/react-bootstrap-table2-example/examples/pagination/custom-pagination.js b/packages/react-bootstrap-table2-example/examples/pagination/custom-pagination.js index f45690497..078f75934 100644 --- a/packages/react-bootstrap-table2-example/examples/pagination/custom-pagination.js +++ b/packages/react-bootstrap-table2-example/examples/pagination/custom-pagination.js @@ -47,6 +47,7 @@ const options = { lastPageTitle: 'Last page', showTotal: true, paginationTotalRenderer: customTotal, + disablePageTitle: true, sizePerPageList: [{ text: '5', value: 5 }, { @@ -82,6 +83,7 @@ const options = { lastPageTitle: 'Last page', showTotal: true, paginationTotalRenderer: customTotal, + disablePageTitle: true, sizePerPageList: [{ text: '5', value: 5 }, { diff --git a/packages/react-bootstrap-table2-example/examples/pagination/standalone-size-per-page.js b/packages/react-bootstrap-table2-example/examples/pagination/standalone-size-per-page.js index 40526a212..477c0a204 100644 --- a/packages/react-bootstrap-table2-example/examples/pagination/standalone-size-per-page.js +++ b/packages/react-bootstrap-table2-example/examples/pagination/standalone-size-per-page.js @@ -74,6 +74,7 @@ export default class StandaloneSizePerPage extends React.Component { return (
{ @@ -84,7 +85,7 @@ export default class StandaloneSizePerPage extends React.Component {
( +
+

{ `This Expand row is belong to rowKey ${row.id}` }

+

You can render anything here, also you can add additional data on every row object

+

expandRow.renderer callback will pass the origin row object to you

+
+ ) +}; + +const expandRow2 = { + className: (isExpanded, row, rowIndex) => { + if (rowIndex > 2) return 'expanding-foo'; + return 'expanding-bar'; + }, + renderer: row => ( +
+

{ `This Expand row is belong to rowKey ${row.id}` }

+

You can render anything here, also you can add additional data on every row object

+

expandRow.renderer callback will pass the origin row object to you

+
+ ) +}; + + +const sourceCode1 = `\ +import BootstrapTable from 'react-bootstrap-table-next'; + +const columns = // omit... + +const expandRow = { + className: 'expanding-foo', + renderer: row => ( +
.....
+ ) +}; + + +`; + +const sourceCode2 = `\ +import BootstrapTable from 'react-bootstrap-table-next'; + +const columns = // omit... + +const expandRow = { + className: (isExpanded, row, rowIndex) => { + if (rowIndex > 2) return 'expanding-foo'; + return 'expanding-bar'; + }, + renderer: row => ( +
...
+ ) +}; + + +`; + +export default () => ( +
+ + { sourceCode1 } + + { sourceCode2 } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/row-expand/index.js b/packages/react-bootstrap-table2-example/examples/row-expand/index.js index 0a089046e..eb21023c7 100644 --- a/packages/react-bootstrap-table2-example/examples/row-expand/index.js +++ b/packages/react-bootstrap-table2-example/examples/row-expand/index.js @@ -18,9 +18,9 @@ const columns = [{ }]; const expandRow = { - renderer: row => ( + renderer: (row, rowIndex) => (
-

{ `This Expand row is belong to rowKey ${row.id}` }

+

{ `This Expand row is belong to rowKey ${row.id} and index: ${rowIndex}` }

You can render anything here, also you can add additional data on every row object

expandRow.renderer callback will pass the origin row object to you

diff --git a/packages/react-bootstrap-table2-example/examples/row-expand/parent-row-classname.js b/packages/react-bootstrap-table2-example/examples/row-expand/parent-row-classname.js new file mode 100644 index 000000000..d384c3742 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/row-expand/parent-row-classname.js @@ -0,0 +1,106 @@ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import Code from 'components/common/code-block'; +import { productsExpandRowsGenerator } from 'utils/common'; + +const products = productsExpandRowsGenerator(); + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const expandRow1 = { + parentClassName: 'parent-expand-foo', + renderer: row => ( +
+

{ `This Expand row is belong to rowKey ${row.id}` }

+

You can render anything here, also you can add additional data on every row object

+

expandRow.renderer callback will pass the origin row object to you

+
+ ) +}; + +const expandRow2 = { + parentClassName: (isExpanded, row, rowIndex) => { + if (rowIndex > 2) return 'parent-expand-foo'; + return 'parent-expand-bar'; + }, + renderer: row => ( +
+

{ `This Expand row is belong to rowKey ${row.id}` }

+

You can render anything here, also you can add additional data on every row object

+

expandRow.renderer callback will pass the origin row object to you

+
+ ) +}; + + +const sourceCode1 = `\ +import BootstrapTable from 'react-bootstrap-table-next'; + +const columns = // omit... + +const expandRow = { + parentClassName: 'parent-expand-foo', + renderer: row => ( +
.....
+ ) +}; + + +`; + +const sourceCode2 = `\ +import BootstrapTable from 'react-bootstrap-table-next'; + +const columns = // omit... + +const expandRow = { + parentClassName: (isExpanded, row, rowIndex) => { + if (rowIndex > 2) return 'parent-expand-foo'; + return 'parent-expand-bar'; + }, + renderer: row => ( +
...
+ ) +}; + + +`; + +export default () => ( +
+ + { sourceCode1 } + + { sourceCode2 } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/row-selection/non-selectable-rows-class.js b/packages/react-bootstrap-table2-example/examples/row-selection/non-selectable-rows-class.js new file mode 100644 index 000000000..a1a8df7da --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/row-selection/non-selectable-rows-class.js @@ -0,0 +1,61 @@ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const products = productsGenerator(); + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const selectRow = { + mode: 'checkbox', + clickToSelect: true, + nonSelectable: [0, 2, 4], + nonSelectableClasses: 'row-index-bigger-than-2101' +}; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const selectRow = { + mode: 'checkbox', + clickToSelect: true, + nonSelectable: [0, 2, 4], + nonSelectableClasses: 'row-index-bigger-than-2101' +}; + + +`; + +export default () => ( +
+ + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/row-selection/non-selectable-rows-style.js b/packages/react-bootstrap-table2-example/examples/row-selection/non-selectable-rows-style.js new file mode 100644 index 000000000..d3fd7f0fd --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/row-selection/non-selectable-rows-style.js @@ -0,0 +1,61 @@ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const products = productsGenerator(); + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const selectRow = { + mode: 'checkbox', + clickToSelect: true, + nonSelectable: [0, 2, 4], + nonSelectableStyle: { backgroundColor: 'gray' } +}; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const selectRow = { + mode: 'checkbox', + clickToSelect: true, + nonSelectable: [0, 2, 4], + nonSelectableStyle: { backgroundColor: 'gray' } +}; + + +`; + +export default () => ( +
+ + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/search/custom-match-function.js b/packages/react-bootstrap-table2-example/examples/search/custom-match-function.js new file mode 100644 index 000000000..afcccd111 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/search/custom-match-function.js @@ -0,0 +1,116 @@ +/* eslint react/prop-types: 0 */ +/* eslint no-unused-vars: 0 */ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const { SearchBar } = Search; +const products = productsGenerator(); + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; +import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit'; + +const { SearchBar } = Search; +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +// Implement startWith instead of contain +function customMatchFunc({ + searchText, + value, + column, + row +}) { + if (typeof value !== 'undefined') { + return value.startsWith(searchText); + } + return false; +} + +export default () => ( +
+ + { + props => ( +
+

Input something at below input field:

+ +
+ +
+ ) + } +
+ { sourceCode } +
+); +`; + +// Implement startWith instead of contain +function customMatchFunc({ + searchText, + value, + column, + row +}) { + if (typeof value !== 'undefined') { + return `${value}`.toLowerCase().startsWith(searchText.toLowerCase()); + } + return false; +} + +export default () => ( +
+

Custom a search match function by startWith instead of contain

+ + { + props => ( +
+

Input something at below input field:

+ +
+ +
+ ) + } +
+ { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/search/search-hook.js b/packages/react-bootstrap-table2-example/examples/search/search-hook.js new file mode 100644 index 000000000..3abbe3bca --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/search/search-hook.js @@ -0,0 +1,91 @@ +/* eslint react/prop-types: 0 */ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const { SearchBar } = Search; +const products = productsGenerator(); + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; +import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit'; + +const { SearchBar } = Search; +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const afterSearch = (newResult) => { + console.log(newResult); +}; + + + { + props => ( +
+

Input something at below input field:

+ +
+ +
+ ) + } +
+`; + +const afterSearch = (newResult) => { + console.log(newResult); +}; + +export default () => ( +
+ + { + props => ( +
+

Input something at below input field:

+ +
+ +
+ ) + } +
+ { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/search/searchable-column.js b/packages/react-bootstrap-table2-example/examples/search/searchable-column.js new file mode 100644 index 000000000..dc9b29340 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/search/searchable-column.js @@ -0,0 +1,87 @@ +/* eslint react/prop-types: 0 */ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const { SearchBar } = Search; +const products = productsGenerator(); + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name', + searchable: false +}, { + dataField: 'price', + text: 'Product Price', + searchable: false +}]; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; +import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit'; + +const { SearchBar } = Search; +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name', + searchable: false +}, { + dataField: 'price', + text: 'Product Price', + searchable: false +}]; + + + { + props => ( +
+

Input something at below input field:

+ +
+ +
+ ) + } +
+`; + +export default () => ( +
+ + { + props => ( +
+

Column name and price is unsearchable

+ +
+ +
+ ) + } +
+ { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/sort/custom-sort-value.js b/packages/react-bootstrap-table2-example/examples/sort/custom-sort-value.js new file mode 100644 index 000000000..74e7f84d5 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/sort/custom-sort-value.js @@ -0,0 +1,78 @@ +/* eslint no-unused-vars: 0 */ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import Code from 'components/common/code-block'; +import { jobsGenerator1 } from 'utils/common'; + +const jobs = jobsGenerator1(8); + +const types = ['Cloud Service', 'Message Service', 'Add Service', 'Edit Service', 'Money']; + +const columns = [{ + dataField: 'id', + text: 'Job ID' +}, { + dataField: 'name', + text: 'Job Name' +}, { + dataField: 'owner', + text: 'Job Owner' +}, { + dataField: 'type', + text: 'Job Type', + sort: true, + formatter: (cell, row) => types[cell], + sortValue: (cell, row) => types[cell] +}]; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; + +const types = ['Cloud Service', 'Message Service', 'Add Service', 'Edit Service', 'Money']; + +const columns = [{ + dataField: 'id', + text: 'Job ID' +}, { + dataField: 'name', + text: 'Job Name' +}, { + dataField: 'owner', + text: 'Job Owner' +}, { + dataField: 'type', + text: 'Job Type', + sort: true, + formatter: (cell, row) => types[cell], + sortValue: (cell, row) => types[cell] +}]; + + +`; + +export default class Test extends React.Component { + constructor(props) { + super(props); + this.state = { data: jobs }; + } + + handleClick = () => { + this.setState(() => { + const newProducts = jobsGenerator1(21); + return { + data: newProducts + }; + }); + } + + render() { + return ( +
+ + + { sourceCode } +
+ ); + } +} diff --git a/packages/react-bootstrap-table2-example/examples/sort/one-time-sort-configuration.js b/packages/react-bootstrap-table2-example/examples/sort/one-time-sort-configuration.js new file mode 100644 index 000000000..93e012e80 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/sort/one-time-sort-configuration.js @@ -0,0 +1,98 @@ +/* eslint no-unused-vars: 0 */ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const products = productsGenerator(); + +const columns = [{ + dataField: 'id', + text: 'Product ID', + sort: true +}, { + dataField: 'name', + text: 'Product Name', + sort: true +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; + +const columns = [{ + dataField: 'id', + text: 'Product ID', + sort: true +}, { + dataField: 'name', + text: 'Product Name', + sort: true +}, { + dataField: 'price', + text: 'Product Price' +}]; + +class OnetimeSortConfiguration extends React.Component { + sortFunc = (a, b, order, dataField) => { + if (order === 'asc') { + return b - a; + } + return a - b; // desc + } + + render() { + const sortOption = { + // No need to configure sortFunc per column + sortFunc: this.sortFunc, + // No need to configure sortCaret per column + sortCaret: (order, column) => { + if (!order) return (  Desc/Asc); + else if (order === 'asc') return (  Desc/Asc); + else if (order === 'desc') return (  Desc/Asc); + return null; + } + }; + + return ( +
+ + + { sourceCode } +
+ ); + } +} +`; + +export default class OnetimeSortConfiguration extends React.Component { + sortFunc = (a, b, order, dataField) => { + if (order === 'asc') { + return b - a; + } + return a - b; // desc + } + + render() { + const sortOption = { + sortFunc: this.sortFunc, + sortCaret: (order, column) => { + if (!order) return (  Desc/Asc); + else if (order === 'asc') return (  Desc/Asc); + else if (order === 'desc') return (  Desc/Asc); + return null; + } + }; + + return ( +
+

Reverse Sorting Table

+ + { sourceCode } +
+ ); + } +} diff --git a/packages/react-bootstrap-table2-example/examples/sort/sort-management.js b/packages/react-bootstrap-table2-example/examples/sort/sort-management.js new file mode 100644 index 000000000..32a5e01ce --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/sort/sort-management.js @@ -0,0 +1,118 @@ +/* eslint no-console: 0 */ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const products = productsGenerator(); + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; + +class SortManagement extends React.Component { + state = { + field: null, + order: null + } + + handleSort = (field, order) => { + this.setState({ + field, + order + }); + } + + handleSortById = () => { + this.setState({ + field: 'id', + order: 'desc' + }); + } + + render() { + const columns = [{ + dataField: 'id', + text: 'Product ID', + sort: true, + onSort: this.handleSort + }, { + dataField: 'name', + text: 'Product Name', + sort: true, + onSort: this.handleSort + }, { + dataField: 'price', + text: 'Product Price' + }]; + return ( +
+ + + { sourceCode } +
+ ); + } +} +`; + +export default class SortManagement extends React.Component { + state = { + field: null, + order: null + } + + handleSort = (field, order) => { + this.setState({ + field, + order + }); + } + + handleSortById = () => { + this.setState({ + field: 'id', + order: 'desc' + }); + } + + render() { + const columns = [{ + dataField: 'id', + text: 'Product ID', + sort: true, + onSort: this.handleSort + }, { + dataField: 'name', + text: 'Product Name', + sort: true, + onSort: this.handleSort + }, { + dataField: 'price', + text: 'Product Price' + }]; + return ( +
+ + + { sourceCode } +
+ ); + } +} diff --git a/packages/react-bootstrap-table2-example/package.json b/packages/react-bootstrap-table2-example/package.json index d2f3a6e93..0c4b58ca0 100644 --- a/packages/react-bootstrap-table2-example/package.json +++ b/packages/react-bootstrap-table2-example/package.json @@ -1,6 +1,6 @@ { "name": "react-bootstrap-table2-example", - "version": "1.0.27", + "version": "1.0.41", "description": "", "main": "index.js", "private": true, diff --git a/packages/react-bootstrap-table2-example/src/utils/common.js b/packages/react-bootstrap-table2-example/src/utils/common.js index beea31b88..131e30877 100644 --- a/packages/react-bootstrap-table2-example/src/utils/common.js +++ b/packages/react-bootstrap-table2-example/src/utils/common.js @@ -29,6 +29,11 @@ export const withOnSale = rows => rows.map((row) => { return row; }); +export const withRandomPrice = rows => rows.map((row) => { + row.price = Math.floor((Math.random() * 10) + 2000); + return row; +}); + export const productsQualityGenerator = (quantity = 5, factor = 0) => Array.from({ length: quantity }, (value, index) => ({ id: index + factor, @@ -69,8 +74,10 @@ const endDate = new Date(); export const stockGenerator = (quantity = 5) => Array.from({ length: quantity }, (value, index) => ({ id: index, - name: `Todo item ${index}`, + name: `Stock Name ${index}`, price: Math.floor((Math.random() * 2) + 1), + visible: Math.random() > 0.5, + quality: index % 3, inStockDate: new Date(startDate.getTime() + Math.random() * (endDate.getTime() - startDate.getTime())) })); diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index 732c5b22e..757cbad18 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -18,6 +18,7 @@ import TabIndexCellTable from 'examples/basic/tabindex-column'; // bootstrap 4 import Bootstrap4DefaultSortTable from 'examples/bootstrap4/sort'; +import Bootstrap4CaptionTable from 'examples/bootstrap4/caption-table'; import Bootstrap4RowSelectionTable from 'examples/bootstrap4/row-selection'; import Bootstrap4PaginationTable from 'examples/bootstrap4/pagination'; import Bootstrap4ColumnToggleTable from 'examples/bootstrap4/column-toggle'; @@ -68,6 +69,7 @@ import TextFilterCaseSensitive from 'examples/column-filter/text-filter-caseSens import CustomTextFilter from 'examples/column-filter/custom-text-filter'; import CustomFilterValue from 'examples/column-filter/custom-filter-value'; import SelectFilter from 'examples/column-filter/select-filter'; +import ConfigureSelectFilterOptions from 'examples/column-filter/select-filter-option-type'; import SelectFilterWithDefaultValue from 'examples/column-filter/select-filter-default-value'; import SelectFilterComparator from 'examples/column-filter/select-filter-like-comparator'; import SelectFilterWithPreservedOptionsOrder from 'examples/column-filter/select-filter-preserve-option-order'; @@ -91,6 +93,7 @@ import AdvanceCustomFilter from 'examples/column-filter/advance-custom-filter'; import ClearAllFilters from 'examples/column-filter/clear-all-filters'; import FilterHooks from 'examples/column-filter/filter-hooks'; import CustomFilterLogic from 'examples/column-filter/custom-filter-logic'; +import FilterPosition from 'examples/column-filter/filter-position'; // work on rows import RowStyleTable from 'examples/rows/row-style'; @@ -103,6 +106,9 @@ import EnableSortTable from 'examples/sort/enable-sort-table'; import DefaultSortTable from 'examples/sort/default-sort-table'; import DefaultSortDirectionTable from 'examples/sort/default-sort-direction'; import SortEvents from 'examples/sort/sort-events'; +import SortManagement from 'examples/sort/sort-management'; +import OneTimeSortConfiguration from 'examples/sort/one-time-sort-configuration'; +import CustomSortValue from 'examples/sort/custom-sort-value'; import CustomSortTable from 'examples/sort/custom-sort-table'; import CustomSortCaretTable from 'examples/sort/custom-sort-caret'; import HeaderSortingClassesTable from 'examples/sort/header-sorting-classes'; @@ -131,6 +137,7 @@ import TextareaEditorTable from 'examples/cell-edit/textarea-editor-table'; import CheckboxEditorTable from 'examples/cell-edit/checkbox-editor-table'; import DateEditorTable from 'examples/cell-edit/date-editor-table'; import CustomEditorTable from 'examples/cell-edit/custom-editor-table'; +import CellEditorWithDataType from 'examples/cell-edit/cell-edit-with-data-type'; // work on row selection import SingleSelectionTable from 'examples/row-selection/single-selection'; @@ -148,6 +155,8 @@ import HeaderStyleTable from 'examples/row-selection/header-style'; import HideSelectAllTable from 'examples/row-selection/hide-select-all'; import CustomSelectionTable from 'examples/row-selection/custom-selection'; import NonSelectableRowsTable from 'examples/row-selection/non-selectable-rows'; +import NonSelectableRowsStyleTable from 'examples/row-selection/non-selectable-rows-style'; +import NonSelectableRowsClassTable from 'examples/row-selection/non-selectable-rows-class'; import SelectionBgColorTable from 'examples/row-selection/selection-bgcolor'; import SelectionHooks from 'examples/row-selection/selection-hooks'; import HideSelectionColumnTable from 'examples/row-selection/hide-selection-column'; @@ -164,6 +173,8 @@ import ExpandOnlyOne from 'examples/row-expand/expand-only-one'; import CustomExpandColumn from 'examples/row-expand/custom-expand-column'; import ExpandColumnPosition from 'examples/row-expand/expand-column-position'; import ExpandHooks from 'examples/row-expand/expand-hooks'; +import ParentRowClassName from 'examples/row-expand/parent-row-classname'; +import ExpandingRowClassName from 'examples/row-expand/expanding-row-classname'; // pagination import PaginationTable from 'examples/pagination'; @@ -186,10 +197,13 @@ import CustomePaginationWithSearch from 'examples/pagination/custom-page-list-wi import SearchTable from 'examples/search'; import ClearSearchButton from 'examples/search/clear-search-button'; import DefaultSearch from 'examples/search/default-search'; +import SearchHooks from 'examples/search/search-hook'; import DefaultCustomSearch from 'examples/search/default-custom-search'; import FullyCustomSearch from 'examples/search/fully-custom-search'; import SearchFormattedData from 'examples/search/search-formatted'; import CustomSearchValue from 'examples/search/custom-search-value'; +import SearchableColumn from 'examples/search/searchable-column'; +import CustomMatchFunction from 'examples/search/custom-match-function'; // CSV import ExportCSV from 'examples/csv'; @@ -202,12 +216,14 @@ import CSVColumnType from 'examples/csv/csv-column-type'; import CustomCSVButton from 'examples/csv/custom-csv-button'; import ExportCustomData from 'examples/csv/export-custom-data'; import CustomCSV from 'examples/csv/custom-csv'; +import ExportTableFooter from 'examples/csv/export-footer'; // Column toggle import BasicColumnToggle from 'examples/column-toggle'; import DefaultVisibility from 'examples/column-toggle/default-visibility'; import StylingColumnToggle from 'examples/column-toggle/styling-toggle-list'; import CustomToggleList from 'examples/column-toggle/custom-toggle-list'; +import ColumnToggleWithFilter from 'examples/column-toggle/column-toggle-with-filter'; // loading overlay import EmptyTableOverlay from 'examples/loading-overlay/empty-table-overlay'; @@ -257,6 +273,7 @@ storiesOf('Basic Table', module) storiesOf('Bootstrap 4', module) .addDecorator(bootstrapStyle(BOOTSTRAP_VERSION.FOUR)) .add('Sort table with bootstrap 4', () => ) + .add('Table Caption bootstrap 4', () => ) .add('Row selection table with bootstrap 4', () => ) .add('Pagination table with bootstrap 4', () => ) .add('Column Toggle with bootstrap 4', () => ) @@ -297,6 +314,7 @@ storiesOf('Column Filter', module) .add('Text Filter with Case Sensitive', () => ) // add another filter type example right here. .add('Select Filter', () => ) + .add('Configure Select Filter Options', () => ) .add('Select Filter with Default Value', () => ) .add('Select Filter with Comparator', () => ) .add('MultiSelect Filter', () => ) @@ -305,6 +323,7 @@ storiesOf('Column Filter', module) .add('Number Filter with Default Value', () => ) .add('Date Filter', () => ) .add('Date Filter with Default Value', () => ) + .add('Filter Position', () => ) .add('Custom Text Filter', () => ) .add('Custom Select Filter', () => ) .add('Custom Number Filter', () => ) @@ -349,6 +368,9 @@ storiesOf('Sort Table', module) .add('Default Sort Table', () => ) .add('Default Sort Direction Table', () => ) .add('Sort Events', () => ) + .add('Sort Management', () => ) + .add('One-time Sort Configuation', () => ) + .add('Custom Sort Value', () => ) .add('Custom Sort Fuction', () => ) .add('Custom Sort Caret', () => ) .add('Custom Classes on Sorting Header Column', () => ) @@ -377,7 +399,8 @@ storiesOf('Cell Editing', module) .add('Textarea Editor', () => ) .add('Checkbox Editor', () => ) .add('Date Editor', () => ) - .add('Custom Editor', () => ); + .add('Custom Editor', () => ) + .add('Cell Editor with Data Type', () => ); storiesOf('Row Selection', module) .addDecorator(bootstrapStyle()) @@ -397,6 +420,8 @@ storiesOf('Row Selection', module) .add('Custom Selection', () => ) .add('Selection Background Color', () => ) .add('Not Selectabled Rows', () => ) + .add('Not Selectabled Rows Style', () => ) + .add('Not Selectabled Rows Class', () => ) .add('Selection Hooks', () => ) .add('Hide Selection Column', () => ) .add('Custom Selection Column Style', () => ) @@ -412,7 +437,9 @@ storiesOf('Row Expand', module) .add('Expand Only One Row at The Same Time', () => ) .add('Custom Expand Indicator', () => ) .add('Expand Column Position', () => ) - .add('Expand Hooks', () => ); + .add('Expand Hooks', () => ) + .add('Custom Parent Row ClassName', () => ) + .add('Custom Expanding Row ClassName', () => ); storiesOf('Pagination', module) .addDecorator(bootstrapStyle()) @@ -438,16 +465,20 @@ storiesOf('Table Search', module) .add('Clear Search Button', () => ) .add('Default Search Table', () => ) .add('Default Custom Search', () => ) + .add('Search Hooks', () => ) + .add('Searchable Column', () => ) .add('Fully Custom Search', () => ) - .add('Search Fromatted Value', () => ) - .add('Custom Search Value', () => ); + .add('Search Formatted Value', () => ) + .add('Custom Search Value', () => ) + .add('Custom match function', () => ); storiesOf('Column Toggle', module) .addDecorator(bootstrapStyle()) .add('Basic Column Toggle', () => ) .add('Default Visibility', () => ) .add('Styling Column Toggle', () => ) - .add('Custom Column Toggle', () => ); + .add('Custom Column Toggle', () => ) + .add('Column Toggle with Filter', () => ); storiesOf('Export CSV', module) .addDecorator(bootstrapStyle()) @@ -460,7 +491,8 @@ storiesOf('Export CSV', module) .add('CSV Column Type', () => ) .add('Custom CSV Button', () => ) .add('Export Custom Data', () => ) - .add('Custom CSV', () => ); + .add('Custom CSV', () => ) + .add('Export Table Footer', () => ); storiesOf('EmptyTableOverlay', module) .addDecorator(bootstrapStyle()) diff --git a/packages/react-bootstrap-table2-example/stories/stylesheet/base-table/_index.scss b/packages/react-bootstrap-table2-example/stories/stylesheet/base-table/_index.scss index beaf76d7a..d8de7253f 100644 --- a/packages/react-bootstrap-table2-example/stories/stylesheet/base-table/_index.scss +++ b/packages/react-bootstrap-table2-example/stories/stylesheet/base-table/_index.scss @@ -1,4 +1,4 @@ -table.foo { +.foo { background-color: $grey-500; } diff --git a/packages/react-bootstrap-table2-example/stories/stylesheet/row-expand/_index.scss b/packages/react-bootstrap-table2-example/stories/stylesheet/row-expand/_index.scss new file mode 100644 index 000000000..a5a5f2f98 --- /dev/null +++ b/packages/react-bootstrap-table2-example/stories/stylesheet/row-expand/_index.scss @@ -0,0 +1,7 @@ +.expanding-foo, .parent-expand-foo { + background-color: coral; +} + +.expanding-bar, .parent-expand-bar { + background-color: aqua; +} \ No newline at end of file diff --git a/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss b/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss index 14959a691..435b84697 100644 --- a/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss +++ b/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss @@ -12,3 +12,4 @@ @import "http://github.com/sort/index"; @import "http://github.com/search/index"; @import "http://github.com/loading-overlay/index"; +@import "http://github.com/row-expand/index"; \ No newline at end of file diff --git a/packages/react-bootstrap-table2-filter/README.md b/packages/react-bootstrap-table2-filter/README.md index b38007ec0..70f45914f 100644 --- a/packages/react-bootstrap-table2-filter/README.md +++ b/packages/react-bootstrap-table2-filter/README.md @@ -2,7 +2,7 @@ `react-bootstrap-table2` separate the filter core code base to [`react-bootstrap-table2-filter`](https://github.com/react-bootstrap-table/react-bootstrap-table2/tree/develop/packages/react-bootstrap-table2-filter), so there's a little bit different when you use column filter than `react-bootstrap-table`. In the following, we are going to show you how to enable the column filter: -**[Live Demo For Column Filter](https://github.com/react-bootstrap-table/react-bootstrap-table2/blob/gh-pages-src/storybook/index.html?selectedKind=Column%20Filter)** +**[Live Demo For Column Filter](https://react-bootstrap-table.github.io/react-bootstrap-table2/storybook/index.html?selectedKind=Column%20Filter)** **[API&Props Definitation](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/filter-props.html)** @@ -64,7 +64,8 @@ const priceFilter = textFilter({ comparator: Comparator.EQ, // default is Comparator.LIKE caseSensitive: true, // default is false, and true will only work when comparator is LIKE style: { ... }, // your custom styles on input - delay: 1000 // how long will trigger filtering after user typing, default is 500 ms + delay: 1000, // how long will trigger filtering after user typing, default is 500 ms + id: 'id', // assign a unique value for htmlFor attribute, it's useful when you have same dataField across multiple table in one page }); // omit... @@ -110,12 +111,15 @@ const qualityFilter = selectFilter({ comparator: Comparator.LIKE, // default is Comparator.EQ style: { ... }, // your custom styles on input withoutEmptyOption: true // hide the default select option + id: 'id', // assign a unique value for htmlFor attribute, it's useful when you have same dataField across multiple table in one page }); // omit... ``` -> Note, the selectOptions can be an array also: +> Note, the selectOptions can be an array or a function which return an array: + +### Array as options ```js const selectOptions = [ @@ -133,6 +137,24 @@ const columns = [ }) }]; ``` +### Function as options + +```js +const selectOptions = [ + { value: 0, label: 'good' }, + { value: 1, label: 'Bad' }, + { value: 2, label: 'unknown' } +]; +const columns = [ + ..., { + dataField: 'quality', + text: 'Product Quailty', + formatter: cell => selectOptions.find(opt => opt.value === cell).label, + filter: selectFilter({ + options: () => selectOptions + }) +}]; +``` The benifit is `react-bootstrap-table2` will render the select options by the order of array. @@ -177,6 +199,7 @@ const qualityFilter = multiSelectFilter({ comparator: Comparator.LIKE, // default is Comparator.EQ style: { ... }, // your custom styles on input withoutEmptyOption: true // hide the default select option + id: 'id', // assign a unique value for htmlFor attribute, it's useful when you have same dataField across multiple table in one page }); // omit... @@ -216,6 +239,7 @@ const numberFilter = numberFilter({ numberStyle: { backgroundColor: 'cadetblue', margin: '0px' }, // custom the style on number input/select numberClassName: 'custom-number-class', // custom the class on ber input/select defaultValue: { number: 2103, comparator: Comparator.GT } // default value + id: 'id', // assign a unique value for htmlFor attribute, it's useful when you have same dataField across multiple table in one page }) // omit... @@ -255,6 +279,7 @@ const dateFilter = dateFilter({ dateStyle: { backgroundColor: 'cadetblue', margin: '0px' }, // custom the style on date input dateClassName: 'custom-date-class', // custom the class on date input defaultValue: { date: new Date(2018, 0, 1), comparator: Comparator.GT } // default value + id: 'id', // assign a unique value for htmlFor attribute, it's useful when you have same dataField across multiple table in one page }) // omit... @@ -310,3 +335,54 @@ Following properties is valid in `FILTER_TYPES`: * NUMBER * DATE * MULTISELECT + +### Position +Default filter is rendered inside the table column header, but you can choose to render them as a row by `filterPosition`: + +#### Render in the top of table body + +```js + +``` + +#### Render in the bottom of table body +```js + +``` + +## Configuration + +`filterFactory` is a factory function for initializing some internal config. Below is available options for `filterFactory`: + +### afterFilter +This hook function will be called with two arguments(new filter result and filter object) when filtering completed. + +```js +function afterFilter(newResult, newFilters) { + console.log(newResult); + console.log(newFilters); +} + +export default () => ( +
+ +
+); +``` diff --git a/packages/react-bootstrap-table2-filter/package.json b/packages/react-bootstrap-table2-filter/package.json index 21e22f0a0..4db71b8b2 100644 --- a/packages/react-bootstrap-table2-filter/package.json +++ b/packages/react-bootstrap-table2-filter/package.json @@ -1,6 +1,6 @@ { "name": "react-bootstrap-table2-filter", - "version": "1.1.10", + "version": "1.3.3", "description": "it's a column filter addon for react-bootstrap-table2", "main": "./lib/index.js", "repository": { diff --git a/packages/react-bootstrap-table2-filter/src/components/date.js b/packages/react-bootstrap-table2-filter/src/components/date.js index 578f55829..54bb761ea 100644 --- a/packages/react-bootstrap-table2-filter/src/components/date.js +++ b/packages/react-bootstrap-table2-filter/src/components/date.js @@ -83,14 +83,27 @@ class DateFilter extends Component { return optionTags; } + getDefaultComparator() { + const { defaultValue, filterState } = this.props; + if (filterState && filterState.filterVal) { + return filterState.filterVal.comparator; + } + if (defaultValue && defaultValue.comparator) { + return defaultValue.comparator; + } + return ''; + } + getDefaultDate() { - let defaultDate = ''; - const { defaultValue } = this.props; + // Set the appropriate format for the input type=date, i.e. "YYYY-MM-DD" + const { defaultValue, filterState } = this.props; + if (filterState && filterState.filterVal && filterState.filterVal.date) { + return dateParser(filterState.filterVal.date); + } if (defaultValue && defaultValue.date) { - // Set the appropriate format for the input type=date, i.e. "YYYY-MM-DD" - defaultDate = dateParser(new Date(defaultValue.date)); + return dateParser(new Date(defaultValue.date)); } - return defaultDate; + return ''; } applyFilter(value, comparator, isInitial) { @@ -115,17 +128,20 @@ class DateFilter extends Component { render() { const { + id, placeholder, - column: { text }, + column: { dataField, text }, style, comparatorStyle, dateStyle, className, comparatorClassName, - dateClassName, - defaultValue + dateClassName } = this.props; + const comparatorElmId = `date-filter-comparator-${dataField}${id ? `-${id}` : ''}`; + const inputElmId = `date-filter-column-${dataField}${id ? `-${id}` : ''}`; + return (
e.stopPropagation() } @@ -134,25 +150,25 @@ class DateFilter extends Component { > -