Reputation: 130
I am working on a project in which I am trying to show a div
of content that says No results found for if the user types letters in the search input that do not match any filter in the list. I've tried using this similar solution as reference: React: How to show message when result is zero in react, but without success.
Here is a snippet of my code and one solution (of many) I have tried so far:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
searchQuery: ""
};
}
handleSearchQuery = event => {
this.setState({ searchQuery: event.target.value });
};
resetInputField = () => {
this.setState({ searchQuery: "" });
};
render() {
const { subContent, type, options, label } = this.props;
const { searchQuery } = this.state;
return (
<div
style={{
display: "grid",
alignItems: "center",
width: "100%",
margin: "0 0 24px 0",
fontSize: "14px"
}}
>
<div style={sx.rangeInputContainer}>
<input
style={sx.rangeInputLong}
type="text"
placeholder={placeholderText}
onChange={this.handleSearchQuery}
value={searchQuery}
/>
</div>
<div>
{options
.filter(
option =>
option.label
.toLowerCase()
.includes(searchQuery.toLowerCase()) || !searchQuery
)
.map((option, index) => {
return option.label.length !== 0 ? (
<div key={index} style={sx.filterOption}>
<SquareCheckbox
type="checkbox"
id={"multiSelectCheckbox-" + option.label}
/>
<label
style={{ color: "#FFF" }}
htmlFor={"multiSelectCheckbox-" + option.label}
>
{option.label}
</label>
</div>
) : (
<div
key={index}
style={{
display: "flex",
alignItems: "center",
marginTop: "16px"
}}
>
<img
style={{ width: "20px", cursor: "pointer" }}
src={resetIconSVG}
onClick={this.resetInputField}
/>
<div style={{ marginLeft: "16px" }}>
No results found for {searchQuery}
</div>
</div>
);
})}
</div>
</div>
);
}
}
Here's a snippet of options, which is in my parent component:
this.state = {
filters: [
{
label: 'Materials',
type: FILTER_TYPE.MULTI_SELECT,
expandedHandle: ()=> {
this.handleExpandedToggle('Materials'); },
options:materials,
expanded:false,
},
{
label: 'Status',
type: FILTER_TYPE.SELECT,
expandedHandle: ()=> { this.handleExpandedToggle('Status');
},
options: status,
expanded:false,
},
],
};
And the dummy .json data I am using:
export const materials = [
{ value: 'brass', label: 'brass' },
{ value: 'chrome', label: 'chrome' },
{ value: 'ceramic', label: 'ceramic' },
{ value: 'glass', label: 'glass' },
{ value: 'concrete', label: 'concrete' },
];
export const status = [
{ value: 'Show All', label: 'Show All' },
{ value: 'Enabled Only', label: 'Enabled Only' },
];
Upvotes: 0
Views: 5225
Reputation: 1241
Seems like your using a ternary operator inside of a return on your filter method. I would put the filter into a variable
const filteredOptions = options.filter(option => option.label.toLowerCase().includes(searchQuery.toLowerCase()) || !searchQuery).map((option, index) => {
return option.label.length !== 0 ? <div key={index} style={sx.filterOption}>
<SquareCheckbox type='checkbox' id={'multiSelectCheckbox-' + option.label} />
<label style={{ color: '#FFF' }} htmlFor={'multiSelectCheckbox-' + option.label}> {option.label} </label>
</div> })
and in your render use the ternary to check the length of the array
render {
return (
{filteredOptions.length > 0 ? filteredOptions : <div style = {{ marginLeft: '16px' }}>No results found for { searchQuery }</div>}
)
}
Upvotes: 2
Reputation: 10179
I've made an assumption about your options
data, hopefully this helps (I simplified the codes)
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
searchQuery: ''
};
}
handleSearchQuery = event => {
this.setState({ searchQuery: event.target.value });
};
resetInputField = () => {
this.setState({ searchQuery: '' });
};
render() {
const { searchQuery } = this.state;
const options = [
{ label: 'react' },
{ label: 'angular' },
{ label: 'vue' }
];
const filteredOptions = options.filter(
option =>
option.label.toLowerCase().includes(searchQuery.toLowerCase()) ||
!searchQuery
);
return (
<div>
<div>
<input
type="text"
onChange={this.handleSearchQuery}
value={searchQuery}
/>
</div>
<div>
{filteredOptions.length > 0 ? (
filteredOptions.map((option, index) => {
return <div key={index}>{option.label}</div>;
})
) : (
<div>
No results found for {searchQuery}
</div>
)}
</div>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Upvotes: 4