0

Lets say I have an array of objects:

const options = [
 {
  text: "this is the text",
  description: "The word 'test' should be bold"
 },
 {
  text: "this is the text",
  description: "The word 'another-word' should be bold"
 }
]

the component renders something like this:

return (
  {
   options.map(option => {
    <p className="text-green-500">{option.description}</p>
  })
 }
)

Now I have to make the word/s "test" and "another-word" bold respectively. In some cases it has to only be characters inside a word.

Grant Solomons
  • 181
  • 1
  • 1
  • 11

3 Answers3

0

I answered it by replacing the value of description. instead of:

description: "this is the text"

I changed it too:

description: <div>this is the <strong>text></strong></div>
Grant Solomons
  • 181
  • 1
  • 1
  • 11
-1

You could create a function which replaces the string in '' with a <b> wrappers.

const highlight = (text) => text.replace(/'([^']+)'/g, "<b>$1</b>")

Then set the innerHTML like this:

return options.map(({ description }) => 
          <p dangerouslySetInnerHTML={{ __html: highlight(description) }}></p>
        )

You need to sanitize the string before doing this if these string are user inputs.

const highlight = (text) => text.replace(/'([^']+)'/g, "<b>$1</b>")

function App() {
  const options = [{
      text: "this is the text",
      description: "The word 'test' should be bold"
    },
    {
      text: "this is the text",
      description: "The word 'another-word' should be bold"
    }
  ]
  
  return options.map(({ description }) => 
          <p dangerouslySetInnerHTML={{ __html: highlight(description) }}></p>
        )
};


ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

You can avoid the innerHTML route entirely. In that case, you need split each string into fragments and then render them.

const highlight = (text) =>
  Array.from(text.matchAll(/([^']*)'*([^']*)'*([^']*)/g), ([m, p1, p2, p3]) =>
    m ? (
      <>
        {p1}
        <b>{p2}</b>
        {p3}
      </>
    ) : null
  );

And render it like this:

  return options.map(({ description }) => 
          <p>{highlight(description)}</p>
        )
adiga
  • 34,372
  • 9
  • 61
  • 83
  • @pilchard I haven't copied from anywhere. And I was just trying out the alternative which doesn't involve innerHTML and I've updated the answer with that. – adiga Jan 04 '23 at 12:55
  • That's fair, but still a [duplicate](https://stackoverflow.com/questions/63037066/how-to-bold-specific-text-in-a-string-in-a-react-js-app). – pilchard Jan 04 '23 at 12:57
  • The above regex fails for a substring which in between the delimiting single quotes features one or many escaped single quotes like e.g. [`'test\'s'`](https://regex101.com/r/4rnZ8A/1) – Peter Seliger Jan 04 '23 at 13:35
  • @PeterSeliger It highlights `test` as intended. OP hasn't mentioned anything about escaping `'` with a backslash – adiga Jan 04 '23 at 13:41
  • @adiga ... The comment is a generic one. It does not criticize but informs. One could also read it as hint to the OP to rethink the OP's use case and/or acceptance criteria. – Peter Seliger Jan 04 '23 at 13:48
-1

This is probably the easiest way to do it, just return a chunk of JSX from a function that deals with bolding the part of the text.

Stackblitz to run the code: https://stackblitz.com/edit/react-ts-gewz6v?file=App.tsx,index.tsx

const options = [
    {
      text: 'this is the text',
      description: "The word 'test' should be bold",
    },
    {
      text: 'this is the text',
      description: "The word 'another-word' should be bold",
    },
  ];

  const boldText = (text) => {
    const termToBold = text.match(/'([^']+)'/)[1];
    const startIndex = text.toLowerCase().indexOf("'");
    return (
      <React.Fragment>
        {text.slice(0, startIndex)}
        <strong>
          {text.slice(startIndex, startIndex + 2 + termToBold.length)}
        </strong>
        {text.slice(startIndex + 2 + termToBold.length)}
      </React.Fragment>
    );
  };

  return (
    <div>
      {' '}
      {options.map((option) => {
        return <p className="text-green-500">{boldText(option.description)}</p>;
      })}
    </div>
  );
End
  • 591
  • 3
  • 10
  • Only works when there's exactly one item in `''` – adiga Jan 04 '23 at 13:30
  • The above regex fails for a substring which in between the delimiting single quotes features one or many escaped single quotes like e.g. [`'test\'s'`](https://regex101.com/r/4rnZ8A/1) – Peter Seliger Jan 04 '23 at 13:37
  • 1
    @adiga ... _"It highlights test as intended. OP hasn't mentioned anything about ... [ ... ] – adiga"_ ... more than one word in between the quotes. – Peter Seliger Jan 04 '23 at 13:52
  • @adiga ... _"2) escaping of quotes is a very rare edge case"_ ... not taking care and / or being aware of escaped characters is the most common reason for breaking code if it comes to string parsing / evaluation. – Peter Seliger Jan 04 '23 at 15:08