简体   繁体   中英

Make letters from a word bold based on user input

I have a search component in my app and when the user input some texts it filters data based on the user input and shows a list of filtered data. What i want to do is to make the text that is searched by the user bold in the filtered data. So for example if i search 'Jo', the filtered data should show as Jo hn / Jo seph / Jo e Rogan

i can figure out a way to make the entire word bold but cannot figure out a way to bold only the part where user typed.

Pretty simple. Just split and join with bold or strong tag.

let searchStr = "Jo"
name.split(searchStr ).join('<b>'+ searchStr +'</b>');

 let searchStr = "Jo"; let name = "John"; document.getElementById('res').innerHTML = name.split(searchStr).join('<b>'+ searchStr +'</b>');
 <h2>Searching "Jo" in John</h2> <p id="res"></p>

You want to change how each string in the filtered data is rendered, based on the search term.

You can use the search term to create a regex, then add <strong> tags to each string based on the regex.

If you don't want to use dangerouslySetInnerHtml then you can do something like this:

const data = ["John", "Banjo", "Jojo", "Bob Jones", "John Johnson", "James"];

const searchTerm = "jo";

const searchTermRegex = new RegExp(
  // Escape special regex characters in the search term,
  // otherwise you will get an invalid regex
  `(${searchTerm.replace(/[.\\+*?[^\]$(){}=!<>|:-]/g, "\\$&")})`,
  "gi"
);

const getBoldFilteredText = (text, term) => {
  const substrings = text.split(searchTermRegex);
  return (
    <div>
      {substrings.map((substring) =>
        substring.toLowerCase() === term.toLowerCase() ? (
          <strong>{substring}</strong>
        ) : (
          substring
        )
      )}
    </div>
  );
};

return <div>{data.map((s) => getBoldFilteredText(s, searchTerm))}</div>;

Here's a way of doing it that doesn't use dangerouslySetInnerHTML or open you up to XSS attacks.

Explanation: String#split with a regex capturing group ( /(...)/ ) includes the captured text in the results at odd-numbered indexes. For example, 'baba'.split(/(b)/) gives you ["", "b", "a", "b", "a"] . Once you have these results, you can map the odd (matched) results to strong elements and the even ones to React.Fragment s.

Demo

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping
const regexEscape = str => str.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&')

const boldify = searchStr => targetStr => {
  return targetStr
    .split(new RegExp(`(${regexEscape(searchStr)})`, 'i'))
    .map((part, idx) =>
      idx % 2 ? (
        <strong key={idx}>{part}</strong>
      ) : (
        <React.Fragment key={idx}>{part}</React.Fragment>
      )
    )
}

const SearchForm = () => {
  const [searchStr, setSearchStr] = useState('');

  return (
    <form onSubmit={e => e.preventDefault()}>
      <input
        type='text'
        value={searchStr}
        onChange={e => setSearchStr(e.currentTarget.value)}
      />

      <ul>
        {list.map(item => {
          return <li>{boldify(searchStr)(item)}</li>;
        })}
      </ul>
    </form>
  )
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM