0

Could anyone help me with this problem?

I have an HTML document with a bunch of paragraphs elements inside it and I'd like to put a element at its beginning. The content was created by the user, using a WYSIWYG editor for instance.

E.g:

<p>Some text was written here</p>
<p>and here</p>
<p>and here</p>

should become:

<p><span></span>Some text was written here</p>
<p><span></span>and here</p>
<p><span></span>and here</p>

Is there a way to do such thing with ReactJS since I can't modify directly the DOM ?

Danilo
  • 41
  • 7
  • Possible duplicate of [Append element in tag right before contents with Javascript](https://stackoverflow.com/questions/10657487/append-element-in-tag-right-before-contents-with-javascript) – mindlis Aug 19 '18 at 05:06
  • This doesn't sound like a valid use case for React, and even if React could do this you're better off using native JavaScript: `const pTags = document.querySelectorAll('p');` `for (let i = 0; i < pTags.length - 1; i++) { pTags[i].prepend(document.createElement('span')); }` – Tim Ellison Aug 19 '18 at 15:18
  • 1
    ReactJs advices against the manipulation of DOM outside of it scope. this would prevent react from keeping track of the DOM tree and hence updating it correctly – Faical ARAB Aug 19 '18 at 15:40

1 Answers1

1

First let assume the prop which holds the paragraph is content.

Before rendering content you need parse it and alter it as a String, to do that add this method to you component

AddLeadingSpan( content ){

    // pattern for the openeing P tag
    const targetEl = /<p>/gi;

    // substitute for the matching result
    const subsEl = "<p><span>im a span tag </span>"; // add some text for relevance

    // simply use the native string API to do the replacement
    return content.replace( targetEl, subsEl);
}

the above method shouldn't be called directly from the render function due to the fact that it returns a string which will be printed as a string.

To solve that problem we need another method (which in this case will act as a middleware ) :

renderAsHTML( content ){
    return(
      {__html:this.AddLeadingSpan( content ) }
    )
}

Finally let go to the render method:

 render(){
     return(
         <div dangerouslySetInnerHTML={this.renderAsHTML( this.props.content )}>
         </div>
     )
 }

You need to invoke the dangerouslySetInnerHTML to do things the React way, for more info check dangerouslySetInnerHTML, but you need to sanitize content to prevent against cross-site scripting (XSS)

Faical ARAB
  • 387
  • 3
  • 14