Reputation: 1204
I have a search and dropdown options on my ReactJS page which I want to synchronize. Meaning that whenever you select an element from the dropdown options, the elements on the screen display only the selected filter.
The search input currently works but I am having issues with the select options. I found a working example (this one here) of a select filter but I am having issues adapting it for my solution.
I think that this function here is the main one for filtering data but I am quite unsure:
changeOption: function(type, e) {
var val = e.target.value;
this.props.changeOption(val, type);
}
How can I filter data based on select options value?
Here is a JSFiddle example of my code: JS Fiddle Example
Upvotes: 1
Views: 6849
Reputation: 7492
You will have to store the selected value in the select
tag in your state, and filter your outputs depending on it :
The state :
this.state = {
isLoading: false,
data: [],
searchString: '',
roleFilter: null
};
Trigger function :
changedRole = ev => {
this.setState({ roleFilter: ev.target.value })
}
Change event :
<select className="category-select" name="categories" onChange={this.changedRole}>
Filtering :
{text.filter(info => roleFilter ? info.role.includes(roleFilter) : true).map(info => (
<div className="display">
<span className="role">Role: {info.role}</span><span>, Salary: {info.salary}</span>
</div>
))}
The full working code :
class Hello extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: false,
data: [],
searchString: '',
roleFilter: null
};
}
componentDidMount() {
this.fetchData();
}
handleChange = e => {
this.setState({ searchString: e.target.value.trim().toLowerCase() });
}
fetchData() {
fetch("https://api.myjson.com/bins/kr5kk")
.then(response => response.json())
.then(json => {
this.setState({
isLoaded: true,
data: json
});
})
.catch(error => console.log("parsing failed", error));
}
changedRole = ev => {
this.setState({ roleFilter: ev.target.value })
}
render() {
var { isLoaded, data, roleFilter, searchString } = this.state;
let text = data;
if (searchString) {
text = text.filter(info => info.role.toLowerCase().match(searchString));
}
return (
<div>
<input type="text" id="searchbar" value={searchString} onChange={this.handleChange}
placeholder="Search by Role" name="device">
</input>
<select className="category-select" name="categories" onChange={this.changedRole}>
<option value={''}></option>
{text.map(info => (
<option value={info.role}>{info.role}</option>
))}
</select>
{text.filter(info => roleFilter ? info.role.includes(roleFilter) : true).map(info => (
<div className="display">
<span className="role">Role: {info.role}</span><span>, Salary: {info.salary}</span>
</div>
))}
</div>
);
}
}
ReactDOM.render(
<Hello name="World" />,
document.getElementById('container')
);
.display{
background-color:#b6d0f9;
margin-top:10px;
padding-top:10px;
padding-bottom:10px;
}
.role{
color:red;
}
#searchbar{
margin-right:150px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.3.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.3.1/umd/react-dom.production.min.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
Upvotes: 3
Reputation: 2036
You need to add an event listener on the select in order to catch the value when it changes. For example:
<select
onChange={ () => this.handleSelectChange() }
className="category-select" name="categories"
>
{text.map(info => (
<option value={info.role}>{info.role}</option>
))}
</select>
Then you need to save the current value of the select in the state of the component and filter the list according to it, the same way you do for the search.
See this. Probably duplicate.
Upvotes: 0