diff --git a/docs/README.md b/docs/README.md
index b5bd0bd..56f1fa3 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -17,6 +17,7 @@
* [hover](#hover)
* [condensed](#condensed)
* [id](#id)
+* [tabIndexCell](#tabIndexCell)
* [classes](#classes)
* [wrapperClasses](#wrapperClasses)
* [headerClasses](#headerClasses)
@@ -112,6 +113,10 @@ Same as bootstrap `.table-condensed` class for making a table more compact by cu
### id - [String]
Customize id on `table` element.
+
+### tabIndexCell - [Bool]
+Enable the `tabIndex` attribute on `
` element.
+
### classes - [String]
Customize class on `table` element.
diff --git a/packages/react-bootstrap-table2-example/examples/basic/tabindex-column.js b/packages/react-bootstrap-table2-example/examples/basic/tabindex-column.js
new file mode 100644
index 0000000..144cdce
--- /dev/null
+++ b/packages/react-bootstrap-table2-example/examples/basic/tabindex-column.js
@@ -0,0 +1,54 @@
+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'
+}];
+
+
+`;
+
+export default () => (
+
+
+ { sourceCode }
+
+);
diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js
index 3dbcede..519542e 100644
--- a/packages/react-bootstrap-table2-example/stories/index.js
+++ b/packages/react-bootstrap-table2-example/stories/index.js
@@ -14,6 +14,7 @@ import CustomizedIdClassesTable from 'examples/basic/customized-id-classes';
import CaptionTable from 'examples/basic/caption-table';
import LargeTable from 'examples/basic/large-table';
import ExposedAPITable from 'examples/basic/exposed-function';
+import TabIndexCellTable from 'examples/basic/tabindex-column';
// bootstrap 4
import Bootstrap4DefaultSortTable from 'examples/bootstrap4/sort';
@@ -195,7 +196,8 @@ storiesOf('Basic Table', module)
.add('Customized id and class table', () => )
.add('Table with caption', () => )
.add('Large Table', () => )
- .add('Exposed API', () => );
+ .add('Exposed API', () => )
+ .add('Enable tabIndex on Cell', () => );
storiesOf('Bootstrap 4', module)
.addDecorator(bootstrapStyle(BOOTSTRAP_VERSION.FOUR))
diff --git a/packages/react-bootstrap-table2/src/body.js b/packages/react-bootstrap-table2/src/body.js
index 7bcd373..a32a82e 100644
--- a/packages/react-bootstrap-table2/src/body.js
+++ b/packages/react-bootstrap-table2/src/body.js
@@ -5,7 +5,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import _ from './utils';
-import Row from './row/simple-row';
+import SimpleRow from './row/simple-row';
import RowAggregator from './row/aggregate-row';
import RowSection from './row/row-section';
import Const from './const';
@@ -24,6 +24,7 @@ class Body extends React.Component {
const {
columns,
data,
+ tabIndexCell,
keyField,
isEmpty,
noDataIndication,
@@ -45,7 +46,7 @@ class Body extends React.Component {
}
content = ;
} else {
- let RowComponent = Row;
+ let RowComponent = SimpleRow;
const selectRowEnabled = selectRow.mode !== Const.ROW_SELECT_DISABLED;
const expandRowEnabled = !!expandRow.renderer;
@@ -73,11 +74,13 @@ class Body extends React.Component {
const baseRowProps = {
key,
row,
+ tabIndexCell,
columns,
keyField,
cellEdit,
value: key,
rowIndex: index,
+ visibleColumnSize,
attrs: rowEvents || {},
...additionalRowProps
};
diff --git a/packages/react-bootstrap-table2/src/bootstrap-table.js b/packages/react-bootstrap-table2/src/bootstrap-table.js
index 1a1d16d..053cac1 100644
--- a/packages/react-bootstrap-table2/src/bootstrap-table.js
+++ b/packages/react-bootstrap-table2/src/bootstrap-table.js
@@ -43,6 +43,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
data,
columns,
keyField,
+ tabIndexCell,
id,
classes,
striped,
@@ -89,6 +90,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
+ |
{
expandColumnRenderer ? expandColumnRenderer({
expanded
diff --git a/packages/react-bootstrap-table2/src/row-selection/selection-cell.js b/packages/react-bootstrap-table2/src/row-selection/selection-cell.js
index 8d46da1..3d6f023 100644
--- a/packages/react-bootstrap-table2/src/row-selection/selection-cell.js
+++ b/packages/react-bootstrap-table2/src/row-selection/selection-cell.js
@@ -15,6 +15,7 @@ export default class SelectionCell extends Component {
onRowSelect: PropTypes.func,
disabled: PropTypes.bool,
rowIndex: PropTypes.number,
+ tabIndex: PropTypes.number,
clickToSelect: PropTypes.bool,
selectionRenderer: PropTypes.func
}
@@ -29,7 +30,8 @@ export default class SelectionCell extends Component {
this.props.rowIndex !== nextProps.rowIndex ||
this.props.selected !== nextProps.selected ||
this.props.disabled !== nextProps.disabled ||
- this.props.rowKey !== nextProps.rowKey;
+ this.props.rowKey !== nextProps.rowKey ||
+ this.props.tabIndex !== nextProps.tabIndex;
return shouldUpdate;
}
@@ -60,14 +62,18 @@ export default class SelectionCell extends Component {
mode: inputType,
selected,
disabled,
+ tabIndex,
selectionRenderer
} = this.props;
+ const attrs = {};
+ if (tabIndex !== -1) attrs.tabIndex = tabIndex;
+
return (
{
({ bootstrap4 }) => (
- |
+ |
{
selectionRenderer ? selectionRenderer({
mode: inputType,
diff --git a/packages/react-bootstrap-table2/src/row/aggregate-row.js b/packages/react-bootstrap-table2/src/row/aggregate-row.js
index 1b3df9d..32c997a 100644
--- a/packages/react-bootstrap-table2/src/row/aggregate-row.js
+++ b/packages/react-bootstrap-table2/src/row/aggregate-row.js
@@ -1,4 +1,5 @@
/* eslint react/prop-types: 0 */
+/* eslint no-plusplus: 0 */
import React from 'react';
import PropTypes from 'prop-types';
import _ from '../utils';
@@ -55,6 +56,8 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
expanded,
selected,
selectable,
+ visibleColumnSize,
+ tabIndexCell,
...rest
} = this.props;
const key = _.get(row, keyField);
@@ -66,6 +69,8 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
newAttrs.onClick = this.createClickEventHandler(newAttrs.onClick);
}
+ let tabIndexStart = (rowIndex * visibleColumnSize) + 1;
+
return (
|
) : null
}
@@ -91,6 +97,7 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
rowIndex={ rowIndex }
selected={ selected }
disabled={ !selectable }
+ tabIndex={ tabIndexCell ? tabIndexStart++ : -1 }
/>
)
: null
@@ -101,6 +108,7 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
keyField={ keyField }
rowIndex={ rowIndex }
shouldUpdate={ this.shouldUpdateRowContent }
+ tabIndexStart={ tabIndexCell ? tabIndexStart : -1 }
{ ...rest }
/>
diff --git a/packages/react-bootstrap-table2/src/row/row-pure-content.js b/packages/react-bootstrap-table2/src/row/row-pure-content.js
index cd1cbfd..5b498ff 100644
--- a/packages/react-bootstrap-table2/src/row/row-pure-content.js
+++ b/packages/react-bootstrap-table2/src/row/row-pure-content.js
@@ -1,5 +1,6 @@
/* eslint react/prop-types: 0 */
/* eslint react/no-array-index-key: 0 */
+/* eslint no-plusplus: 0 */
import React from 'react';
import _ from '../utils';
@@ -25,9 +26,12 @@ export default class RowPureContent extends React.Component {
onStart,
clickToEdit,
dbclickToEdit,
- EditingCellComponent
+ EditingCellComponent,
+ tabIndexStart
} = this.props;
+ let tabIndex = tabIndexStart;
+
return columns.map((column, index) => {
if (!column.hidden) {
const { dataField } = column;
@@ -87,6 +91,10 @@ export default class RowPureContent extends React.Component {
editableCell = column.editable(content, row, rowIndex, index);
}
+ if (tabIndexStart !== -1) {
+ cellAttrs.tabIndex = tabIndex++;
+ }
+
return (
-
+
);
}
}
-Row.propTypes = {
+SimpleRow.propTypes = {
row: PropTypes.object.isRequired,
rowIndex: PropTypes.number.isRequired,
columns: PropTypes.array.isRequired,
@@ -47,11 +54,11 @@ Row.propTypes = {
attrs: PropTypes.object
};
-Row.defaultProps = {
+SimpleRow.defaultProps = {
editable: true,
style: {},
className: null,
attrs: {}
};
-export default Row;
+export default SimpleRow;
diff --git a/packages/react-bootstrap-table2/test/cell.test.js b/packages/react-bootstrap-table2/test/cell.test.js
index e2e42ab..1187c13 100644
--- a/packages/react-bootstrap-table2/test/cell.test.js
+++ b/packages/react-bootstrap-table2/test/cell.test.js
@@ -198,6 +198,26 @@ describe('Cell', () => {
});
});
+ describe('when props.tabIndex is change', () => {
+ const column = { dataField: 'name', text: 'Product Name' };
+ beforeEach(() => {
+ props = {
+ row,
+ columnIndex: 1,
+ rowIndex: 1,
+ tabIndex: 5,
+ column
+ };
+ wrapper = shallow(
+ | );
+ });
+
+ it('should return true', () => {
+ nextProps = { ...props, tabIndex: 2 };
+ expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true);
+ });
+ });
+
describe('if column.isDummyField is true', () => {
describe('when content is change', () => {
const column = { dataField: '', text: 'Product Name', isDummyField: true };
diff --git a/packages/react-bootstrap-table2/test/row-selection/selection-cell.test.js b/packages/react-bootstrap-table2/test/row-selection/selection-cell.test.js
index 7de9a40..fb6f798 100644
--- a/packages/react-bootstrap-table2/test/row-selection/selection-cell.test.js
+++ b/packages/react-bootstrap-table2/test/row-selection/selection-cell.test.js
@@ -57,6 +57,27 @@ describe('', () => {
});
});
+ describe('when tabIndex prop has been changed', () => {
+ beforeEach(() => {
+ props = {
+ selected: false,
+ mode,
+ rowIndex,
+ disabled: false,
+ tabIndex: 0,
+ rowKey: 1
+ };
+ wrapper = shallow(
+
+ );
+ });
+
+ it('should return true', () => {
+ nextProps = { ...props, tabIndex: 2 };
+ expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true);
+ });
+ });
+
describe('when disabled prop has been changed', () => {
beforeEach(() => {
props = {
diff --git a/packages/react-bootstrap-table2/test/row/row-pure-content.test.js b/packages/react-bootstrap-table2/test/row/row-pure-content.test.js
index 70982c5..3000f93 100644
--- a/packages/react-bootstrap-table2/test/row/row-pure-content.test.js
+++ b/packages/react-bootstrap-table2/test/row/row-pure-content.test.js
@@ -104,6 +104,47 @@ describe('RowPureContent', () => {
});
});
+ describe('when tabIndexStart prop is -1', () => {
+ beforeEach(() => {
+ wrapper = shallow(
+
+ );
+ });
+
+ it('should not render tabIndex prop on Cell', () => {
+ wrapper.find(Cell).forEach((cell) => {
+ expect(cell.prop('tabIndex')).toBeUndefined();
+ });
+ });
+ });
+
+ describe('when tabIndexStart prop is not -1', () => {
+ const tabIndexStart = 4;
+ beforeEach(() => {
+ wrapper = shallow(
+
+ );
+ });
+
+ it('should render correct tabIndex prop on Cell', () => {
+ wrapper.find(Cell).forEach((cell, i) => {
+ expect(cell.prop('tabIndex')).toEqual(tabIndexStart + i);
+ });
+ });
+ });
+
describe('when editingRowIdx and editingColIdx prop is defined', () => {
const editingRowIdx = rowIndex;
const editingColIdx = 1;
diff --git a/packages/react-bootstrap-table2/test/row/simple-row.test.js b/packages/react-bootstrap-table2/test/row/simple-row.test.js
index 744f3cb..3d0f6c4 100644
--- a/packages/react-bootstrap-table2/test/row/simple-row.test.js
+++ b/packages/react-bootstrap-table2/test/row/simple-row.test.js
@@ -57,6 +57,49 @@ describe('SimpleRow', () => {
expect(wrapper.length).toBe(1);
expect(wrapper.find(RowPureContent)).toHaveLength(1);
});
+
+ describe('when tabIndexCell prop is enable', () => {
+ const visibleColumnSize = 3;
+ beforeEach(() => {
+ wrapper = shallow(
+
+ );
+ });
+
+ it('should render correct tabIndexStart', () => {
+ expect(wrapper.length).toBe(1);
+ expect(wrapper.find(RowPureContent)).toHaveLength(1);
+ expect(wrapper.find(RowPureContent).prop('tabIndexStart')).toBe((rowIndex * visibleColumnSize) + 1);
+ });
+ });
+
+ describe('when tabIndexCell prop is disable', () => {
+ const visibleColumnSize = 3;
+ beforeEach(() => {
+ wrapper = shallow(
+
+ );
+ });
+
+ it('should always render tabIndexStart as -1', () => {
+ expect(wrapper.length).toBe(1);
+ expect(wrapper.find(RowPureContent)).toHaveLength(1);
+ expect(wrapper.find(RowPureContent).prop('tabIndexStart')).toBe(-1);
+ });
+ });
});
describe('shouldComponentUpdate', () => {
| |