arunmmanoharan
arunmmanoharan

Reputation: 2675

Dynamically wrap a js string by span tags which can be dangerously rendered in React

I have a string and I would like to add span tags to the alphabets alone with an aria-label tag. The end result will be dangerously rendered in React. Please advice. This is what I have.

const str = `D = (C - B) / B`;

const addAriaLabels = (str) => {
  function alphaOnly(a) {
    var b = '';
    for (var i = 0; i < a.length; i++) {
      if (a[i] >= 'A' && a[i] <= 'z') b += a[i];
    }
    return b;
  }
  return alphaOnly(str).split('').map(item => `<span aria-label=\'column ${item}\'>${item}</span>`).join('')
}

console.log(addAriaLabels(str))

Expected Output:

<span aria-label='column D'>D</span> = (<span aria-label='column C'>C</span> - <span aria-label='column B'>B</span>) / <span aria-label='column B'>B</span>

I am not sure on how to add back the symbols itself.

Example:

If string is A, result should be <span aria-label="column A">A</span>.

If string is D = (C - B) / B, result should be <span aria-label='column D'>D</span> = (<span aria-label='column C'>C</span> - <span aria-label='column B'>B</span>) / <span aria-label='column B'>B</span>

Upvotes: 2

Views: 635

Answers (2)

Lionel Rowe
Lionel Rowe

Reputation: 5926

You don't need dangerouslySetInnerHTML for this.

Explanation:

  • The regex /([a-z]+)/i matches all substrings of 1 or more Latin alphabet letters, case insensitive.

  • 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 captured, odd-indexed results (idx % 2) to span elements and the even ones to React.Fragments.

addAriaLabels now returns an array of React components, which can be rendered directly inside a parent.

const addAriaLabels = str =>
  str.split(/([a-z]+)/i)
    .map((substr, idx) => idx % 2
      ? <span key={idx} aria-label={`column ${substr}`}>{substr}</span>
      : <React.Fragment key={idx}>{substr}</React.Fragment>)

const Parent = () => {
  const str = `D = (C - B) / B`

  return (
    <>
      {addAriaLabels(str)}
    </>
  )
}

Upvotes: 2

Boussadjra Brahim
Boussadjra Brahim

Reputation: 1

Iterate over the string characters if the current character is an alphabet add that tags to it then assign it to already defined string else just assign the character :

const originalStr = `D = (C - B) / B`

function addAriaLabels(str) {
  let newStr = ''
  for (let i = 0; i < str.length; i++) {
    if (str[i].match(/[A-Z]/g) && str[i].match(/[A-Z]/g).length > 0) {
      newStr += `<span aria-label=\'column ${str[i]}\'>${str[i]}</span>`
    } else {
      newStr += str[i]
    }

  }

  return newStr;
}

console.log(addAriaLabels(originalStr))

Upvotes: 1

Related Questions