mirror of
https://github.com/gosticks/react-bootstrap-table2.git
synced 2026-07-01 06:30:11 +00:00
implement selection context
This commit is contained in:
@@ -42,7 +42,6 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
||||
|
||||
renderTable() {
|
||||
const {
|
||||
store,
|
||||
columns,
|
||||
keyField,
|
||||
id,
|
||||
@@ -74,8 +73,8 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
||||
|
||||
const headerCellSelectionInfo = this.resolveSelectRowPropsForHeader({
|
||||
onAllRowsSelect: this.props.onAllRowsSelect,
|
||||
selected: store.selected,
|
||||
allRowsSelected: isSelectedAll(store)
|
||||
selected: this.props.selected,
|
||||
allRowsSelected: isSelectedAll(this.state.data, this.props.selected)
|
||||
});
|
||||
|
||||
const tableCaption = (caption && <Caption>{ caption }</Caption>);
|
||||
@@ -87,8 +86,8 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
||||
<Header
|
||||
columns={ columns }
|
||||
className={ this.props.headerClasses }
|
||||
sortField={ store.sortField }
|
||||
sortOrder={ store.sortOrder }
|
||||
sortField={ this.props.sortField }
|
||||
sortOrder={ this.props.sortOrder }
|
||||
onSort={ this.props.onSort }
|
||||
onFilter={ this.props.onFilter }
|
||||
onExternalFilter={ this.props.onExternalFilter }
|
||||
@@ -103,7 +102,7 @@ class BootstrapTable extends PropsBaseResolver(Component) {
|
||||
noDataIndication={ noDataIndication }
|
||||
cellEdit={ this.props.cellEdit || {} }
|
||||
selectRow={ cellSelectionInfo }
|
||||
selectedRowKeys={ store.selected }
|
||||
selectedRowKeys={ this.props.selected }
|
||||
rowStyle={ rowStyle }
|
||||
rowClasses={ rowClasses }
|
||||
rowEvents={ rowEvents }
|
||||
@@ -121,7 +120,6 @@ BootstrapTable.propTypes = {
|
||||
remote: PropTypes.oneOfType([PropTypes.bool, PropTypes.shape({
|
||||
pagination: PropTypes.bool
|
||||
})]),
|
||||
store: PropTypes.object,
|
||||
noDataIndication: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
||||
striped: PropTypes.bool,
|
||||
bordered: PropTypes.bool,
|
||||
|
||||
94
packages/react-bootstrap-table2/src/contexts/selection-context.js
vendored
Normal file
94
packages/react-bootstrap-table2/src/contexts/selection-context.js
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
/* eslint react/prop-types: 0 */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Const from '../const';
|
||||
import { getRowByRowId } from '../store/rows';
|
||||
// Consider make selectionHandler become a part of Provider
|
||||
import * as selectionHandler from '../store/selection';
|
||||
|
||||
export default () => {
|
||||
const SelectionContext = React.createContext();
|
||||
|
||||
class SelectionProvider extends React.Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
data: PropTypes.array.isRequired,
|
||||
keyField: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
state = { selected: (this.props.selectRow && this.props.selectRow.selected) || [] };
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.selectRow) {
|
||||
this.setState(() => ({
|
||||
selected: nextProps.selectRow.selected || this.state.selected
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
handleRowSelect = (rowKey, checked, rowIndex, e) => {
|
||||
const { data, keyField, selectRow: { mode, onSelect } } = this.props;
|
||||
const { ROW_SELECT_SINGLE } = Const;
|
||||
|
||||
let currSelected = [...this.state.selected];
|
||||
|
||||
if (mode === ROW_SELECT_SINGLE) { // when select mode is radio
|
||||
currSelected = [rowKey];
|
||||
} else if (checked) { // when select mode is checkbox
|
||||
currSelected.push(rowKey);
|
||||
} else {
|
||||
currSelected = currSelected.filter(value => value !== rowKey);
|
||||
}
|
||||
|
||||
if (onSelect) {
|
||||
const row = getRowByRowId(data, keyField, rowKey);
|
||||
onSelect(row, checked, rowIndex, e);
|
||||
}
|
||||
|
||||
this.setState(() => ({ selected: currSelected }));
|
||||
}
|
||||
|
||||
handleAllRowsSelect = (e) => {
|
||||
const {
|
||||
data,
|
||||
keyField,
|
||||
selectRow: {
|
||||
onSelectAll,
|
||||
nonSelectable
|
||||
}
|
||||
} = this.props;
|
||||
const { selected } = this.state;
|
||||
const anySelected = selectionHandler.isAnySelectedRow(selected, nonSelectable);
|
||||
|
||||
const result = !anySelected;
|
||||
|
||||
const currSelected = result ?
|
||||
selectionHandler.selectableKeys(data, keyField, nonSelectable) :
|
||||
selectionHandler.unSelectableKeys(selected, nonSelectable);
|
||||
|
||||
if (onSelectAll) {
|
||||
onSelectAll(result, selectionHandler.getSelectedRows(data, keyField, currSelected), e);
|
||||
}
|
||||
|
||||
this.setState(() => ({ selected: currSelected }));
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<SelectionContext.Provider
|
||||
value={ {
|
||||
selected: this.state.selected,
|
||||
onRowSelect: this.handleRowSelect,
|
||||
onAllRowsSelect: this.handleAllRowsSelect
|
||||
} }
|
||||
>
|
||||
{ this.props.children }
|
||||
</SelectionContext.Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
return {
|
||||
Provider: SelectionProvider,
|
||||
Consumer: SelectionContext.Consumer
|
||||
};
|
||||
};
|
||||
@@ -1,107 +0,0 @@
|
||||
/* eslint no-param-reassign: 0 */
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Const from '../const';
|
||||
import {
|
||||
isAnySelectedRow,
|
||||
selectableKeys,
|
||||
unSelectableKeys,
|
||||
getSelectedRows
|
||||
} from '../store/selection';
|
||||
import { getRowByRowId } from '../store/rows';
|
||||
|
||||
export default Base =>
|
||||
class RowSelectionWrapper extends Component {
|
||||
static propTypes = {
|
||||
store: PropTypes.object.isRequired,
|
||||
selectRow: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleRowSelect = this.handleRowSelect.bind(this);
|
||||
this.handleAllRowsSelect = this.handleAllRowsSelect.bind(this);
|
||||
|
||||
props.store.selected = props.selectRow.selected || [];
|
||||
this.state = {
|
||||
selectedRowKeys: props.store.selected
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
nextProps.store.selected = nextProps.selectRow.selected || [];
|
||||
this.setState(() => ({
|
||||
selectedRowKeys: nextProps.store.selected
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* row selection handler
|
||||
* @param {String} rowKey - row key of what was selected.
|
||||
* @param {Boolean} checked - next checked status of input button.
|
||||
*/
|
||||
handleRowSelect(rowKey, checked, rowIndex, e) {
|
||||
const { selectRow: { mode, onSelect }, store } = this.props;
|
||||
const { ROW_SELECT_SINGLE } = Const;
|
||||
|
||||
let currSelected = [...store.selected];
|
||||
|
||||
if (mode === ROW_SELECT_SINGLE) { // when select mode is radio
|
||||
currSelected = [rowKey];
|
||||
} else if (checked) { // when select mode is checkbox
|
||||
currSelected.push(rowKey);
|
||||
} else {
|
||||
currSelected = currSelected.filter(value => value !== rowKey);
|
||||
}
|
||||
|
||||
store.selected = currSelected;
|
||||
|
||||
if (onSelect) {
|
||||
const row = getRowByRowId(store)(rowKey);
|
||||
onSelect(row, checked, rowIndex, e);
|
||||
}
|
||||
|
||||
this.setState(() => ({
|
||||
selectedRowKeys: currSelected
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* handle all rows selection on header cell by store.selected
|
||||
*/
|
||||
handleAllRowsSelect(e) {
|
||||
const { store, selectRow: {
|
||||
onSelectAll,
|
||||
nonSelectable
|
||||
} } = this.props;
|
||||
const selected = isAnySelectedRow(store)(nonSelectable);
|
||||
|
||||
const result = !selected;
|
||||
|
||||
const currSelected = result ?
|
||||
selectableKeys(store)(nonSelectable) :
|
||||
unSelectableKeys(store)(nonSelectable);
|
||||
|
||||
|
||||
store.selected = currSelected;
|
||||
|
||||
if (onSelectAll) {
|
||||
onSelectAll(result, getSelectedRows(store), e);
|
||||
}
|
||||
|
||||
this.setState(() => ({
|
||||
selectedRowKeys: currSelected
|
||||
}));
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Base
|
||||
{ ...this.props }
|
||||
onRowSelect={ this.handleRowSelect }
|
||||
onAllRowsSelect={ this.handleAllRowsSelect }
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
export const matchRow = (keyField, id) => row => row[keyField] === id;
|
||||
|
||||
export const getRowByRowId = ({ data, keyField }) => id => data.find(matchRow(keyField, id));
|
||||
export const getRowByRowId = (data, keyField, id) => data.find(matchRow(keyField, id));
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import _ from '../utils';
|
||||
import { getRowByRowId } from './rows';
|
||||
|
||||
export const isSelectedAll = ({ data, selected }) => data.length === selected.length;
|
||||
export const isSelectedAll = (data, selected) => data.length === selected.length;
|
||||
|
||||
export const isAnySelectedRow = ({ selected }) => (skips = []) => {
|
||||
export const isAnySelectedRow = (selected, skips = []) => {
|
||||
if (skips.length === 0) {
|
||||
return selected.length > 0;
|
||||
}
|
||||
return selected.filter(x => !skips.includes(x)).length;
|
||||
};
|
||||
|
||||
export const selectableKeys = ({ data, keyField }) => (skips = []) => {
|
||||
export const selectableKeys = (data, keyField, skips = []) => {
|
||||
if (skips.length === 0) {
|
||||
return data.map(row => _.get(row, keyField));
|
||||
}
|
||||
@@ -19,15 +19,13 @@ export const selectableKeys = ({ data, keyField }) => (skips = []) => {
|
||||
.map(row => _.get(row, keyField));
|
||||
};
|
||||
|
||||
export const unSelectableKeys = ({ selected }) => (skips = []) => {
|
||||
export const unSelectableKeys = (selected, skips = []) => {
|
||||
if (skips.length === 0) {
|
||||
return [];
|
||||
}
|
||||
return selected.filter(x => skips.includes(x));
|
||||
};
|
||||
|
||||
export const getSelectedRows = (store) => {
|
||||
const getRow = getRowByRowId(store);
|
||||
return store.selected.map(k => getRow(k));
|
||||
};
|
||||
export const getSelectedRows = (data, keyField, selected) =>
|
||||
selected.map(k => getRowByRowId(data, keyField, k));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user