mirror of
https://github.com/gosticks/react-table.git
synced 2026-02-04 07:42:47 +00:00
Add filterRender column option to customize the filter that is shown (#162)
* Add filterRender column option to completely customize the filter that is shown * Refactor filterRender as a defaultProp.
This commit is contained in:
parent
e8ebf7c780
commit
cef7fbd780
@ -14,4 +14,5 @@ h1 {
|
||||
|
||||
p {
|
||||
margin-bottom: 15px;
|
||||
line-height: 22px;
|
||||
}
|
||||
20
README.md
20
README.md
@ -229,7 +229,16 @@ These are all of the available props (and their default values) for the main `<R
|
||||
footerStyle: {},
|
||||
getFooterProps: () => ({}),
|
||||
filterMethod: undefined,
|
||||
hideFilter: false
|
||||
hideFilter: false,
|
||||
filterRender: ({filter, onFilterChange}) => (
|
||||
<input type='text'
|
||||
style={{
|
||||
width: '100%'
|
||||
}}
|
||||
value={filter ? filter.value : ''}
|
||||
onChange={(event) => onFilterChange(event.target.value)}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
// Text
|
||||
@ -303,7 +312,7 @@ Or just define them as props
|
||||
columns: [...], // See Header Groups section below
|
||||
|
||||
// Footer
|
||||
footer: 'Header Name' or JSX eg. ({data, column}) => <div>Header Name</div>,
|
||||
footer: 'Footer Name' or JSX eg. ({data, column}) => <div>Footer Name</div>,
|
||||
footerClassName: '', // Set the classname of the `td` element of the column's footer
|
||||
footerStyle: {}, // Set the style of the `td` element of the column's footer
|
||||
getFooterProps: (state, rowInfo, column, instance) => ({}), // A function that returns props to decorate the `td` element of the column's footer
|
||||
@ -313,7 +322,8 @@ Or just define them as props
|
||||
// filter == an object specifying which filter is being applied. Format: {id: [the filter column's id], value: [the value the user typed in the filter field], pivotId: [if filtering on a pivot column, the pivotId will be set to the pivot column's id and the `id` field will be set to the top level pivoting column]}
|
||||
// row == the row of data supplied to the table
|
||||
// column == the column that the filter is on
|
||||
hideFilter: false // If `showFilters` is set on the table, this option will let you selectively hide the filter on a particular row
|
||||
hideFilter: false, // If `showFilters` is set on the table, this option will let you selectively hide the filter on a particular row
|
||||
filterRender: JSX // eg. ({filter, onFilterChange}) => <select onChange={event => onFilterChange(event.target.value)} value={filter ? filter.value : ''}></select> // The value passed to onFilterChange will be the value passed to filter.value of the filterMethod
|
||||
}]
|
||||
```
|
||||
|
||||
@ -622,7 +632,7 @@ Here are the props and their corresponding callbacks that control the state of t
|
||||
onPageSizeChange={(pageSize, pageIndex) => {...}} // Called when the pageSize is changed by the user. The resolve page is also sent to maintain approximate position in the data
|
||||
onSortingChange={(column, shiftKey) => {...}} // Called when a sortable column header is clicked with the column itself and if the shiftkey was held. If the column is a pivoted column, `column` will be an array of columns
|
||||
onExpandRow={(index, event) => {...}} // Called when an expander is clicked. Use this to manage `expandedRows`
|
||||
onFilteringChange={(column, event) => {...}} // Called when a user enters a value into a filter input field. The event is the onChange event of the input field.
|
||||
onFilteringChange={(column, value) => {...}} // Called when a user enters a value into a filter input field or the value passed to the onFilterChange handler by the filterRender option.
|
||||
/>
|
||||
```
|
||||
|
||||
@ -675,6 +685,8 @@ By default the table tries to filter by checking if the row's value starts with
|
||||
|
||||
If you want to override a particular column's filtering method, you can set the `filterMethod` option on a column.
|
||||
|
||||
To completely override the filter that is shown, you can set the `filterRender` column option. Using this option you can specify the JSX that is shown. The option is passed an `onFilterChange` method which must be called with the the value that you wan't to pass to the `filterMethod` option whenever the filter has changed.
|
||||
|
||||
See <a href="http://react-table.js.org/?selectedKind=2.%20Demos&selectedStory=Custom%20Filtering&full=0&down=1&left=1&panelRight=0&downPanel=kadirahq%2Fstorybook-addon-actions%2Factions-panel" target="\_parent">Custom Filtering</a> demo for examples.
|
||||
|
||||
## Component Overrides
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<div id="error-display"></div>
|
||||
<script src="static/preview.1bf8468d20ff1a92c704.bundle.js"></script>
|
||||
<script src="static/preview.2b73b4112ed711a12fa8.bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -1 +0,0 @@
|
||||
{"version":3,"file":"static/preview.1bf8468d20ff1a92c704.bundle.js","sources":["webpack:///static/preview.1bf8468d20ff1a92c704.bundle.js"],"mappings":"AAAA;AAkuDA;AAm/DA;AA+qFA;AAmmFA;AA07OA;AAuwFA;AAwtDA;AA+jEA;AA4uDA;AAi8DA;AA+lDA;AA4yDA;AA28CA;AAw7DA;AAooDA;AA67CA;AAiqDA;AAynEA;AAwxDA;AA+rCA;AA+mDA;AA2lDA;AAkqEA;AAs2DA;AA2zDA;AAo4CA;AAosFA;AAmjGA;AA6sDA;AAw2CA;AAkoCA;AAq8CA;AAu8CA;AAoDA;AA+jFA","sourceRoot":""}
|
||||
File diff suppressed because one or more lines are too long
1
docs/static/preview.2b73b4112ed711a12fa8.bundle.js.map
vendored
Normal file
1
docs/static/preview.2b73b4112ed711a12fa8.bundle.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"static/preview.2b73b4112ed711a12fa8.bundle.js","sources":["webpack:///static/preview.2b73b4112ed711a12fa8.bundle.js"],"mappings":"AAAA;AAkuDA;AA8+DA;AA+qFA;AAmmFA;AA07OA;AAuwFA;AAwtDA;AA+jEA;AA4uDA;AAi8DA;AA+lDA;AA4yDA;AA28CA;AAw7DA;AAooDA;AA67CA;AAiqDA;AAynEA;AAwxDA;AA+rCA;AA+mDA;AA2lDA;AAkqEA;AAs2DA;AA2zDA;AAo4CA;AAitFA;AAmjGA;AA6sDA;AAi1CA;AAosCA;AAm2CA;AAs/CA;AA4HA;AA+jFA","sourceRoot":""}
|
||||
@ -104,7 +104,16 @@ export default {
|
||||
footerStyle: {},
|
||||
getFooterProps: emptyObj,
|
||||
filterMethod: undefined,
|
||||
hideFilter: false
|
||||
hideFilter: false,
|
||||
filterRender: ({filter, onFilterChange}) => (
|
||||
<input type='text'
|
||||
style={{
|
||||
width: '100%'
|
||||
}}
|
||||
value={filter ? filter.value : ''}
|
||||
onChange={(event) => onFilterChange(event.target.value)}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
// Text
|
||||
|
||||
51
src/index.js
51
src/index.js
@ -417,16 +417,16 @@ export default React.createClass({
|
||||
const filter = filtering.find(filter => filter.id === column.id && filter.pivotId === col.id)
|
||||
pivotCols.push(
|
||||
<span key={col.id}
|
||||
style={{display: 'flex', alignContent: 'flex-end', flex: 1}}>
|
||||
style={{flex: 1}}>
|
||||
{!col.hideFilter ? (
|
||||
<input type='text'
|
||||
style={{
|
||||
flex: 1,
|
||||
width: 20
|
||||
}}
|
||||
value={filter ? filter.value : ''}
|
||||
onChange={(event) => this.filterColumn(column, event, col)}
|
||||
/>
|
||||
_.normalizeComponent(col.filterRender,
|
||||
{
|
||||
col,
|
||||
filter,
|
||||
onFilterChange: (value) => (this.filterColumn(column, value, col))
|
||||
},
|
||||
defaults.column.filterRender
|
||||
)
|
||||
) : null}
|
||||
</span>
|
||||
)
|
||||
@ -489,13 +489,14 @@ export default React.createClass({
|
||||
{...rest}
|
||||
>
|
||||
{!column.hideFilter ? (
|
||||
<input type='text'
|
||||
style={{
|
||||
width: `100%`
|
||||
}}
|
||||
value={filter ? filter.value : ''}
|
||||
onChange={(event) => this.filterColumn(column, event)}
|
||||
/>
|
||||
_.normalizeComponent(column.filterRender,
|
||||
{
|
||||
column,
|
||||
filter,
|
||||
onFilterChange: (value) => (this.filterColumn(column, value))
|
||||
},
|
||||
defaults.column.filterRender
|
||||
)
|
||||
) : null}
|
||||
</ThComponent>
|
||||
)
|
||||
@ -593,15 +594,15 @@ export default React.createClass({
|
||||
{...rowInfo}
|
||||
value={rowInfo.rowValues[pivotValKey]}
|
||||
/>
|
||||
) : <span>{row[pivotValKey]} ({rowInfo.subRows.length})</span>}
|
||||
) : <span>{row[pivotValKey]} ({rowInfo.subRows.length})</span>}
|
||||
</span>
|
||||
) : SubComponent ? (
|
||||
<span>
|
||||
<ExpanderComponent
|
||||
isExpanded={isExpanded}
|
||||
/>
|
||||
</span>
|
||||
) : null}
|
||||
) : SubComponent ? (
|
||||
<span>
|
||||
<ExpanderComponent
|
||||
isExpanded={isExpanded}
|
||||
/>
|
||||
</span>
|
||||
) : null}
|
||||
</TdComponent>
|
||||
)
|
||||
}
|
||||
@ -887,7 +888,7 @@ export default React.createClass({
|
||||
style={paginationProps.style}
|
||||
{...paginationProps.rest}
|
||||
/>
|
||||
) : null}
|
||||
) : null}
|
||||
{!pageRows.length && (
|
||||
<NoDataComponent
|
||||
{...noDataProps}
|
||||
|
||||
@ -440,12 +440,12 @@ export default {
|
||||
this.fireOnChange()
|
||||
})
|
||||
},
|
||||
filterColumn (column, event, pivotColumn) {
|
||||
filterColumn (column, value, pivotColumn) {
|
||||
const {filtering} = this.getResolvedState()
|
||||
const {onFilteringChange} = this.props
|
||||
|
||||
if (onFilteringChange) {
|
||||
return onFilteringChange(column, event)
|
||||
return onFilteringChange(column, value)
|
||||
}
|
||||
|
||||
// Remove old filter first if it exists
|
||||
@ -461,10 +461,10 @@ export default {
|
||||
}
|
||||
})
|
||||
|
||||
if (event.target.value !== '') {
|
||||
if (value !== '') {
|
||||
newFiltering.push({
|
||||
id: column.id,
|
||||
value: event.target.value,
|
||||
value: value,
|
||||
pivotId: pivotColumn ? pivotColumn.id : undefined
|
||||
})
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ import ReactTable from '../src/index'
|
||||
|
||||
class Filtering extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
const data = _.map(_.range(5553), d => {
|
||||
@ -33,10 +33,10 @@ class Filtering extends React.Component {
|
||||
data: data
|
||||
}
|
||||
|
||||
this.setTableOption = this.setTableOption.bind(this);
|
||||
this.setTableOption = this.setTableOption.bind(this)
|
||||
}
|
||||
|
||||
render() {
|
||||
render () {
|
||||
const columns = [{
|
||||
header: 'Name',
|
||||
columns: [{
|
||||
@ -54,26 +54,51 @@ class Filtering extends React.Component {
|
||||
columns: [{
|
||||
header: 'Age',
|
||||
accessor: 'age'
|
||||
}]
|
||||
}, {
|
||||
header: 'Over 21',
|
||||
accessor: 'age',
|
||||
id: 'over',
|
||||
render: ({value}) => (value >= 21 ? 'Yes' : 'No'),
|
||||
filterMethod: (filter, row) => {
|
||||
if (filter.value === 'all') {
|
||||
return true
|
||||
}
|
||||
if (filter.value === 'true') {
|
||||
return row[filter.id] >= 21
|
||||
}
|
||||
return row[filter.id] < 21
|
||||
},
|
||||
filterRender: ({filter, onFilterChange}) => (
|
||||
<select
|
||||
onChange={event => onFilterChange(event.target.value)}
|
||||
style={{width: '100%'}}
|
||||
value={filter ? filter.value : 'all'}>
|
||||
<option value="all"></option>
|
||||
<option value="true">Can Drink</option>
|
||||
<option value="false">Can't Drink</option>
|
||||
</select>
|
||||
)
|
||||
}
|
||||
]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div style={{float: "left"}}>
|
||||
<div style={{float: 'left'}}>
|
||||
<h1>Table Options</h1>
|
||||
<table>
|
||||
<tbody>
|
||||
{
|
||||
Object.keys(this.state.tableOptions).map(optionKey => {
|
||||
const optionValue = this.state.tableOptions[optionKey];
|
||||
const optionValue = this.state.tableOptions[optionKey]
|
||||
return (
|
||||
<tr key={optionKey}>
|
||||
<td>{optionKey}</td>
|
||||
<td style={{paddingLeft: 10, paddingTop: 5}}>
|
||||
<input type="checkbox"
|
||||
name={optionKey}
|
||||
checked={optionValue}
|
||||
onChange={this.setTableOption}
|
||||
name={optionKey}
|
||||
checked={optionValue}
|
||||
onChange={this.setTableOption}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@ -122,21 +147,30 @@ class Filtering extends React.Component {
|
||||
</div>
|
||||
<div>
|
||||
<h1>Custom Filters In This Example</h1>
|
||||
<p>The default filter for all columns of a table if it is not specified in the configuration is set to match on values that start with the filter text. Example: age.startsWith("2").</p>
|
||||
<p>This example overrides the default filter behavior by setting the <strong>defaultFilterMethod</strong> table option to match on values that are exactly equal to the filter text. Example: age == "23")</p>
|
||||
<p>The default filter for all columns of a table if it is not specified in the configuration is set to match
|
||||
on values that start with the filter text. Example: age.startsWith("2").</p>
|
||||
<p>This example overrides the default filter behavior by setting
|
||||
the <strong>defaultFilterMethod</strong> table option to match on values that are exactly equal to the
|
||||
filter text. Example: age == "23")</p>
|
||||
<p>Each column can also be customized with the column <strong>filterMethod</strong> option:</p>
|
||||
<p>In this example the firstName column filters on the value starting with and ending with the filter value.</p>
|
||||
<p>In this example the lastName column filters on the value including the filter value anywhere in its text.</p>
|
||||
<p>In this example the firstName column filters on the value starting with and ending with the filter
|
||||
value.</p>
|
||||
<p>In this example the lastName column filters on the value including the filter value anywhere in its
|
||||
text.</p>
|
||||
<p>To completely override the filter that is shown, you can set the <strong>filterRender</strong> column
|
||||
option. Using this option you can specify the JSX that is shown. The option is passed
|
||||
an <strong>onFilterChange</strong> method that must be called with the value that you wan't to
|
||||
pass to the <strong>filterMethod</strong> option whenever the filter has changed.</p>
|
||||
</div>
|
||||
<CodeHighlight>{() => this.getCode()}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
setTableOption(event) {
|
||||
const target = event.target;
|
||||
const value = target.type === 'checkbox' ? target.checked : target.value;
|
||||
const name = target.name;
|
||||
setTableOption (event) {
|
||||
const target = event.target
|
||||
const value = target.type === 'checkbox' ? target.checked : target.value
|
||||
const name = target.name
|
||||
this.setState({
|
||||
tableOptions: {
|
||||
...this.state.tableOptions,
|
||||
@ -145,7 +179,7 @@ class Filtering extends React.Component {
|
||||
})
|
||||
}
|
||||
|
||||
getCode() {
|
||||
getCode () {
|
||||
return `
|
||||
const columns = [{
|
||||
header: 'Name',
|
||||
@ -164,6 +198,30 @@ const columns = [{
|
||||
columns: [{
|
||||
header: 'Age',
|
||||
accessor: 'age'
|
||||
}, {
|
||||
header: 'Over 21',
|
||||
accessor: 'age',
|
||||
id: 'over',
|
||||
render: ({value}) => (value >= 21 ? 'Yes' : 'No'),
|
||||
filterMethod: (filter, row) => {
|
||||
if (filter.value === 'all') {
|
||||
return true
|
||||
}
|
||||
if (filter.value === 'true') {
|
||||
return row[filter.id] >= 21
|
||||
}
|
||||
return row[filter.id] < 21
|
||||
},
|
||||
filterRender: ({filter, onFilterChange}) => (
|
||||
<select
|
||||
onChange={event => onFilterChange(event.target.value)}
|
||||
style={{width: '100%'}}
|
||||
value={filter ? filter.value : 'all'}>
|
||||
<option value="all"></option>
|
||||
<option value="true">Can Drink</option>
|
||||
<option value="false">Can't Drink</option>
|
||||
</select>
|
||||
)
|
||||
}]
|
||||
}]
|
||||
|
||||
@ -203,4 +261,4 @@ export default (
|
||||
}
|
||||
}
|
||||
|
||||
export default () => <Filtering/>
|
||||
export default () => <Filtering />
|
||||
|
||||
Loading…
Reference in New Issue
Block a user