@tannerlinsley when creating a custom filter component the function have the filter object and the onChange callback function. Can I pass another callback function to the filter component? I want to render a dropdown button next to the input which has values like "startWith", "contains" and so on. What could be the best option to do that.
I needed something like this as well. My solution was to create a separate function and component which are passed to each column using the 'filterMethod' and 'Filter' props.
My custom component maintains internal state containing the current filter type and value. When either change the callback method is called with the state as the object.
The function checks a filterType property of the value and switches the filtering method based on that. The filterValue property of the value is used to compare to row values.
Not sure if this is the best way, but it works!
_Note: I am using Material-UI components to render the selection. You'll need to include that library, or recreate the component's render method._
function filterMethod(filter, row) {
// Pivoted rows won't contain the column.
// If that's the case, we set the to true (allowing us to only filter on the current column)
const rowValue = row[filter.id];
if (!rowValue) {
return true;
}
const filterValue = filter.value.filterValue || '';
const filterType = filter.value.filterType;
switch (filterType) {
case 'contains':
return rowValue.indexOf(filterValue) > -1;
case 'starts-with':
return rowValue.startsWith(filterValue);
case 'ends-with':
return rowValue.endsWith(filterValue);
case 'matches':
return rowValue === filterValue;
case 'greater-than':
return rowValue > filterValue;
case 'less-than':
return rowValue < filterValue;
default:
return true;
}
}
class FilterInnerComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
filterType: 'contains',
filterValue: ''
};
this.changeFilterType = this.changeFilterType.bind(this);
this.changeFilterValue = this.changeFilterValue.bind(this);
}
changeFilterType(event, index, filterType) {
const newState = {
...this.state,
filterType
};
// Update local state
this.setState(newState);
// Fire the callback to alert React-Table of the new filter
this.props.onChange(newState);
}
changeFilterValue(event, filterValue) {
const newState = {
...this.state,
filterValue
};
// Update local state
this.setState(newState);
// Fire the callback to alert React-Table of the new filter
this.props.onChange(newState);
}
render() {
return (
<div className="filter">
<SelectField
onChange={this.changeFilterType}
style={{
width: '100%',
height: '40px',
fontSize: '12px'
}}
value={this.state.filterType}
autoWidth
>
<MenuItem value="contains" primaryText="Contains" />
<MenuItem value="matches" primaryText="Matches" />
<MenuItem value="starts-with" primaryText="Starts With" />
<MenuItem value="ends-with" primaryText="Ends With" />
<MenuItem value="greater-than" primaryText="Greater Than" />
<MenuItem value="less-than" primaryText="Less Than" />
</SelectField>
<TextField
onChange={this.changeFilterValue}
style={{
width: '100%',
height: '40px',
float: 'left',
fontSize: '12px'
}}
value={this.state.filterValue}
/>
</div>
);
}
}
@Siaver, I think @scrawfor nailed it. You can render literally whatever you want in the Filter rendering for a column. Just build your filter component as you normally would with however many dropdowns and options you want, and stick it in as the Filter function/component of a column. As long as your custom filter component can call the filter's onChange property with the new filter, you're golden :)
If you have more questions or need help implementing, please join the slack channel :)
@scrawfor @tannerlinsley Thanks a lot for your help!
@scrawfor
Your solution solves my problem for the most part. Even Im implementing a similar approach. I think this should serve as a solid reference for anyone who is implementing filtering by a custom component.
@tannerlinsley do you still have a slack channel?
Not for react-table. I moved the community to spectrum.chat/react-table.
Most helpful comment
I needed something like this as well. My solution was to create a separate function and component which are passed to each column using the 'filterMethod' and 'Filter' props.
My custom component maintains internal state containing the current filter type and value. When either change the callback method is called with the state as the object.
The function checks a filterType property of the value and switches the filtering method based on that. The filterValue property of the value is used to compare to row values.
Not sure if this is the best way, but it works!
_Note: I am using Material-UI components to render the selection. You'll need to include that library, or recreate the component's render method._
Filter Method
Filter Component