diff --git a/docs/columns.md b/docs/columns.md index 55a4003..906536e 100644 --- a/docs/columns.md +++ b/docs/columns.md @@ -11,6 +11,7 @@ Available properties in a column object: * [hidden](#hidden) * [formatter](#formatter) * [formatExtraData](#formatExtraData) +* [type](#type) * [sort](#sort) * [sortFunc](#sortFunc) * [sortCaret](#sortCaret) @@ -132,6 +133,10 @@ 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. diff --git a/packages/react-bootstrap-table2-editor/src/context.js b/packages/react-bootstrap-table2-editor/src/context.js index e9317e2..ea3c1f0 100644 --- a/packages/react-bootstrap-table2-editor/src/context.js +++ b/packages/react-bootstrap-table2-editor/src/context.js @@ -56,12 +56,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 +70,7 @@ export default ( if (_.isFunction(beforeSaveCell)) { const result = beforeSaveCell( oldValue, - newValue, + newValueWithType, row, column, beforeSaveCellDone @@ -78,7 +79,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-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 0000000..28a064b --- /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/src/utils/common.js b/packages/react-bootstrap-table2-example/src/utils/common.js index beea31b..f6baec2 100644 --- a/packages/react-bootstrap-table2-example/src/utils/common.js +++ b/packages/react-bootstrap-table2-example/src/utils/common.js @@ -69,8 +69,9 @@ 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, 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 732c5b2..2add873 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -131,6 +131,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'; @@ -377,7 +378,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()) diff --git a/packages/react-bootstrap-table2/src/const.js b/packages/react-bootstrap-table2/src/const.js index ce1b7e4..9852215 100644 --- a/packages/react-bootstrap-table2/src/const.js +++ b/packages/react-bootstrap-table2/src/const.js @@ -8,5 +8,9 @@ export default { CHECKBOX_STATUS_INDETERMINATE: 'indeterminate', CHECKBOX_STATUS_UNCHECKED: 'unchecked', INDICATOR_POSITION_LEFT: 'left', - INDICATOR_POSITION_RIGHT: 'right' + INDICATOR_POSITION_RIGHT: 'right', + TYPE_STRING: 'string', + TYPE_NUMBER: 'number', + TYPE_BOOLEAN: 'bool', + TYPE_DATE: 'date' }; diff --git a/packages/react-bootstrap-table2/src/header-cell.js b/packages/react-bootstrap-table2/src/header-cell.js index 708800b..3321507 100644 --- a/packages/react-bootstrap-table2/src/header-cell.js +++ b/packages/react-bootstrap-table2/src/header-cell.js @@ -117,6 +117,12 @@ HeaderCell.propTypes = { column: PropTypes.shape({ dataField: PropTypes.string.isRequired, text: PropTypes.string.isRequired, + type: PropTypes.oneOf([ + Const.TYPE_STRING, + Const.TYPE_NUMBER, + Const.TYPE_BOOLEAN, + Const.TYPE_DATE + ]), isDummyField: PropTypes.bool, hidden: PropTypes.bool, headerFormatter: PropTypes.func, diff --git a/packages/react-bootstrap-table2/src/store/operators.js b/packages/react-bootstrap-table2/src/store/operators.js index de055ee..b357006 100644 --- a/packages/react-bootstrap-table2/src/store/operators.js +++ b/packages/react-bootstrap-table2/src/store/operators.js @@ -3,11 +3,13 @@ import * as selection from './selection'; import * as expand from './expand'; import * as mutate from './mutate'; import * as sort from './sort'; +import * as type from './type'; export default { ...rows, ...selection, ...expand, ...mutate, - ...sort + ...sort, + ...type }; diff --git a/packages/react-bootstrap-table2/src/store/type.js b/packages/react-bootstrap-table2/src/store/type.js new file mode 100644 index 0000000..b5084e6 --- /dev/null +++ b/packages/react-bootstrap-table2/src/store/type.js @@ -0,0 +1,18 @@ +import Const from '../const'; + +export const typeConvert = (type, value) => { + if (!type || type === Const.TYPE_STRING) { + return String(value); + } else if (type === Const.TYPE_NUMBER) { + return Number(value); + } else if (type === Const.TYPE_BOOLEAN) { + if (typeof value === 'boolean') { + return value; + } + return value === 'true'; + } else if (type === Const.TYPE_DATE) { + return new Date(value); + } + return value; +}; +