I have a search component that returns data from slideData based on the searchTerm. My goal is to highlight the word that is typed. I think i need to use indexOf or tag but I am struggling with the logic of where to use it? For clarity, the expected result is that if i search for "hamburger" it will display all results with hamburger and highlight "hamburger" in those results.
const [searchTerm, setSearchTerm] = useState("");
const SlideData = [
{
slideIndex: 1,
title: "My name is Bob",
text1: "Bob likes to eat hamburgers",
text2: "Kenny likes to eat hot dogs",
text3: "Terry likes milkshakes"
},
{
slideIndex: 2,
title: "My name is Jill",
text1: "Jill likes to eat hamburgers",
text2: "Joshua likes to eat hot dogs",
text3: "Steven likes milkshakes"
}
]
<div className="search-results">
<ul className="search-list">
{SlideData.filter((item) => {
if (searchTerm === "") {
return null;
} else {
//concat the text properties into variable//
let searchText = item.title + item.text1 + item.text2 + item.text3 + item.text4;
//if the variable contains the search term value//
if (searchText.toLowerCase().includes(searchTerm.toLowerCase())) {
//return those items//
return item;
}
}
}).map((item) => (
//map through the items and display list of results
<div key={item.slideIndex} style={{ marginTop: "20px" }}>
<h4 style={{ color: "white" }}>{item.title}</h4>
<li className="search-item">{item.text1}</li>
<li className="search-item">{item.text1.indexOf(searchTerm)}</li>
<a
className="search-link"
onClick={() => {
context.setCurrentSlide(item.slideIndex);
setSearchTerm("");
}}
>
Go To Slide {item.slideIndex}
</a>
</div>
))}
</ul>
</div>
SOMETHING I AM TRYING
//find the search term in the results//
const highlighted = item.text1.indexOf(searchTerm);
if(searchTerm === -1){
//highlight the term
}else{
//Do nothing
}
In order to target the results with different styles you need to break it out to it's own HTML element.
You can use this regex function
const splitResult = (result) =>
//Split on search result and then simply style the matches
result.split(new RegExp(`(${searchTerm})`, `gi`)).map((piece, index) => {
return (
<span
key={index}
style={{
background:
piece.toLowerCase() === searchTerm.toLocaleLowerCase()
? "YELLOW"
: "TRANSPARENT"
}}
>
{piece}
</span>
);
});
Here's your full component I removed some parts that are not related to the question
export default function App() {
const [searchTerm, setSearchTerm] = useState("");
const splitResult = (result) =>
//Split on search result and then simply style the matches then map through
result.split(new RegExp(`(${searchTerm})`, `gi`)).map((piece, index) => {
return (
<span
key={index}
style={{
background:
piece.toLowerCase() === searchTerm.toLocaleLowerCase()
? "YELLOW"
: "TRANSPARENT"
}}
>
{piece}
</span>
);
});
return (
<div className="search-results">
<ul className="search-list">
{/** Search input */}
<input
type="search"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
{SlideData.filter((item) => {
if (searchTerm === "") {
return null;
} else {
//concat the text properties into variable//
let searchText = item.title + item.text1 + item.text2 + item.text3 + item.text4;
//if the variable contains the search term value//
if (searchText.toLowerCase().includes(searchTerm.toLowerCase())) {
//return those items//
return item;
}
}
return null;
}).map((item) => (
//map through the items and display list of results
<div key={item.slideIndex} style={{ marginTop: "20px" }}>
<h4>{item.title}</h4>
<li>{splitResult(item.text1)}</li>
<li>{item.text1.indexOf(searchTerm)}</li>
</div>
))}
</ul>
</div>
);
}