Reputation: 127
I have a React.js app with a search bar which is similar to, i.e., Google. A user can type some text into an input field, and matching data is fetched and displayed in a dropdown menu below the input.
My issue: I want to bold certain words that are shown in my dropdown - specifically the words in the string that the user has not typed into the input field themselves.
So, for instance, if a user types in the search bar "blue", below it will display all data in the DB which contains the word "blue" i.e. "blue shoes" or "blue sky". I want it that the word that is not typed into the searchbar to be bolded --> sky or shoes
My makeBold function does not work because a) it displays on the browser as <b>blue</b> sky
rather than actually bolded; b) it would bold the keyword the user typed in rather than the other words)
** keyword
is passed to this component by the parent, it contains the text
the user has written in the input field
** searchResults
contains the list of fetched search results passed as an
array of objects
const SearchResults = ({ keyword, searchResults }) => {
const showDropdown = () => {
return searchResults.map((item) => {
if (item.term.includes(keyword.toLowerCase())) {
return (
<div key={item.term}>
<ul>
<li className="input-fields search-results">
{makeBold(item.searchterm)} ({item.nrResults})
</li>
</ul>
</div>
);
}
});
};
const makeBold = (input) => {
var re = new RegExp(keyword, 'g')
return (
input.replace(re, '<b>'+keyword+ '</b>')
)
}
return <div>{keyword ? showDropdown () : null}</div>;
};
So my question is how to bold specific text in my string which has not typed into the input field? Thanks!
Upvotes: 7
Views: 21640
Reputation: 1
this work for /\d{1,2}(.\d)*%/, it could work for u
const MainMessage = ({ msg }) => {
const newExpresion = [];
const newMsg = msg.split(/\s/);
newExpresion.push("");
let i = 0;
newMsg.forEach((element) => {
if (element.match(/\d{1,2}(.\d)*%/)) {
newExpresion.push(<b> {element} </b>);
newExpresion.push("");
i += 2;
} else {
newExpresion[i] = `${newExpresion[i]} ${element}`;
}
});
return <div>{newExpresion.map((item) => item)}</div>;
};
Upvotes: 0
Reputation: 3474
For the sake of completeness, here are my comments in an answer form.
Your problem is basically how to convert a String to JSX. Have a look at How do I convert a string to jsx? - you need to use dangerouslySetInnerHTML
. Be aware that the solution there is vulnerable to XSS attacks though so make sure you trust your input.
An example of how to use dangerouslySetInnerHTML
is below:
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
const keyword = "beans";
const makeBold = item => {
const re = new RegExp(keyword, "g");
return item.replace(re, "<b>" + keyword + "</b>");
};
const items = [
"I really like beans",
"I really don't like beans",
"I really like eggs"
]
ReactDOM.render(<div>
<ul>
{
items.map((item, i) => {
return (
<li
dangerouslySetInnerHTML={{ __html: makeBold(item) }}
key={i}
/>
)
})
}
</ul>
</div>, document.getElementById('root') );
</script>
<div id="root"></div>
Upvotes: 2
Reputation: 34107
You need to dangerouslySetInnerHTML
Sample code below. This is what it does.
i
tag. This is rendered with normal font weight via a CSS rule.Please note that below is a code sample to be used in react context/OP application, this will not work in this site.
const makeBold = (item, keyword) => {
var re = new RegExp(keyword, 'g')
return (
item.replace(re, '<i>'+keyword+ '</i>')
)
}
console.log(makeBold('blue shoes', 'blue'));
.text-bold {
font-weight: bold;
}
.text-bold i {
font-weight: normal;
}
<div className="text-bold">
<ul>
<li dangerouslySetInnerHTML={{__html: makeBold(item, 'blue')}} />
</ul>
</div>
Instead of dangouresly setting the html you can also use the package react-html-parser. This avoids the use of dangerouslySetInnerHTML
Then the code would look like
import ReactHtmlParser from 'react-html-parser';
<div className="text-bold">
<ul>
<li> {ReactHtmlParser(makeBold(item, 'blue')) }
</ul>
</div>
Upvotes: 5
Reputation: 1699
You could use the dangerouslySetInnerHTML attribute.
But as its name suggests, it can be dangerous. If this input is coming from an external source then you have to make sure that it does not contain any unwanted scripts or links!
return (
<div dangerouslySetInnerHTML={{
__html: item.replace(re, '<b>' + keyword + '</b>')
}} />
)
Upvotes: 2