critical_maas
critical_maas

Reputation: 127

How to bold specific text in a string in a React.js app

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

Answers (4)

Nicol&#225;s P
Nicol&#225;s P

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

James Whiteley
James Whiteley

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

kiranvj
kiranvj

Reputation: 34107

You need to dangerouslySetInnerHTML

Sample code below. This is what it does.

  1. Make all text bold via CSS
  2. Our keyword is wrapped in a 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

cy3er
cy3er

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

Related Questions