Raw HTML is getting rendered on DOM in React component - javascript

I am getting below response from the API, and I want to convert it into proper html and would like to render it on dom, but it is rendering raw html and special characters.
example api response:
resp = {
body: "<p>Cali Thirty Seven turned what appeared to be certain defeat into an exhilarating and much-deserved victory late Saturday afternoon at Gulfstream Park. She reasserted herself after relinquishing the lead to 8-5 favorite Stormy Victoria to successfully defend her title in the $100,000 Powder Break Stakes.</p>\r\n<p>"
}
In the react component I am rendering it in the following way:
<p
className="newsDescription"
dangerouslySetInnerHTML={{ __html:this.props.story.desp }}
/>
I tried to escape html but it is not working.

You have to replace whatever html characters you have in your string to the corresponding tags. Since in your example you only have "<p> (which correspond to <p>) you can do this:
validate if this.props.story.desp has a value a is a string and then replace:
<span
className="newsDescription"
dangerouslySetInnerHTML={{ __html: this.props.story.desp.replace(/</g, '<').replace(/>/g, '>')}}
/>
This will generate a <span> element with a <p> element (the paragraph element coming from your API) inside the <span> with your text. Also, notice that this will replace all occurrences for creating the paragraph tags.
Unfortunately there is no generic vanilla javascript function for replacing all possible tags.
Note that I changed the <p> tag to a <span> because block elements should not have other block elements inside. Have a look at this question in SO.

Related

Save line breaks from String in JavaScript object to transfer over to breaks in HTML

sorry if this a pretty basic question but I'm trying to store a multi-paragraph chunk of text in an object in a Pinia store to be converted to text in HTML, but I can't figure out how to transfer paragraph breaks through the Pinia store.
export const useContentStore = defineStore('contentStore', {
state: () => {
return {
guides: [{
description: 'Paragraph one. Paragraph two. Paragraph three.',
}],
}
},
})
<template>
<main class="content-page">
<body>
<p>{{ content.description }}</p>
</body>
</main>
</template>
I'd like there to be some space between each paragraph, I don't know if that would be adding another line between them or something different. I've already tried escaping like \n, adding <br> tags in the text, and using template literals.
This is what my end goal is:
Paragraph one.
Paragraph two.
Paragraph three.
Thanks for any help you can give!
p {
white-space: pre-wrap
}
<p>
Paragraph one.
Paragraph two.
Paragraph three.
</p>
As you can see above, if you use css property white-space: pre-wrap, it can do what you ask, but be carefull, it may cause other weird interactions.
It will preserve whitespaces, newlines, tabs and <br />.

Why is a <div> tag or <form> tag written as a child to a <p> tag in an HTML code rendered by Chrome as not a child, but a sibling of the <p> tag? [duplicate]

As far as I know, this is right:
<div>
<p>some words</p>
</div>
But this is wrong:
<p>
<div>some words</div>
</p>
The first one can pass the W3C validator (XHTML 1.0), but the second can't. I know that nobody will write code like the second one. I just want know why.
And what about other tags' containment relationship?
An authoritative place to look for allowed containment relations is the HTML spec. See, for example, http://www.w3.org/TR/html4/sgml/dtd.html. It specifies which elements are block elements and which are inline. For those lists, search for the section marked "HTML content models".
For the P element, it specifies the following, which indicates that P elements are only allowed to contain inline elements.
<!ELEMENT P - O (%inline;)* -- paragraph -->
This is consistent with http://www.w3.org/TR/html401/struct/text.html#h-9.3.1, which says that the P element "cannot contain block-level elements (including P itself)."
In short, it is impossible to place a <div> element inside a <p> in the DOM because the opening <div> tag will automatically close the <p> element.
According to HTML5, the content model of div elements is flow content
Most elements that are used in the body of documents and applications are categorized as flow content.
That includes p elements, which can only be used where flow content is expected.
Therefore, div elements can contain p elements.
However, the content model of p elements is Phrasing content
Phrasing content is the text of the document, as well as elements that
mark up that text at the intra-paragraph level. Runs of phrasing
content form paragraphs.
That doesn't include div elements, which can only be used where flow content is expected.
Therefore, p elements can't contain div elements.
Since the end tag of p elements can be omitted when the p element is immediately followed by a div element (among others), the following
<p>
<div>some words</div>
</p>
is parsed as
<p></p>
<div>some words</div>
</p>
and the last </p> is an error.
Look at this example from the HTML spec
<!-- Example of data from the client database: -->
<!-- Name: Stephane Boyera, Tel: (212) 555-1212, Email: sb#foo.org -->
<DIV id="client-boyera" class="client">
<P><SPAN class="client-title">Client information:</SPAN>
<TABLE class="client-data">
<TR><TH>Last name:<TD>Boyera</TR>
<TR><TH>First name:<TD>Stephane</TR>
<TR><TH>Tel:<TD>(212) 555-1212</TR>
<TR><TH>Email:<TD>sb#foo.org</TR>
</TABLE>
</DIV>
Did you notice something? : There was no closing tag of the <p> element. a mistake in the specs ? No.
Tip #1: The closing tag of <p> is OPTIONAL
You may ask: But then how would a <p> element knows where to stop?
From w3docs:
If the closing tag is omitted, it is considered that the end of the paragraph matches with the start of the next block-level element.
In simple words: a <div> is a block element and its opening tag will cause the parent <p> to be closed, thus <div> can never be nested inside <p>.
BUT what about the inverse situation ? you may ask
well ...
Tip #2: The closing tag of the <div> element is REQUIRED
According to O’Reilly HTML and XHTML Pocket Reference, Fourth Edition (page 50)
<div> . . . </div>
Start/End Tags
Required/Required
That is, the <div> element's end will only be determined by its closing tag </div> hence a <p> element inside is will NOT break it.
After the X HTML, the conventions has been changed, and now it's a mixture of conventions of XML and HTML, so that is why the second approach is wrong and the W3C validator accepts the things correct that are according to the standards and conventions.
Because the div tag has higher precedence than the p tag. The p tag represents a paragraph tag whereas the div tag represents a document tag.
You can write many paragraphs in a document tag, but you can't write a document in a paragraph. The same as a DOC file.

Angular removes leading whitespace when rendering

At work, I am developing an Angular component that displays a string from its input on the rendered HTML page.
The HTML for displaying the string looks something like this:
<span>{{value}}</span>
where value comes from this.value in the Angular code. For normal strings this works OK, but I have found that Angular strips out leading whitespace. Now I know that HTML itself compresses multiple whitespace into one when rendering the HTML into a visible page, but the whitespace is removed from the HTML itself.
I have verified that the string in the Angular code contains whitespace:
console.log("The string is: [" + this.value + "]");
prints out The string is: [ Hello world!] on the web console. But what appears on the rendered HTML page is:
<span>Hello world!</span>
How can I fix this?
Even if Angular preserves the whitespace, which I assume it is doing, html will strip it down. You have two option to either use tag or do it via css as shown below:
No Preservation <br/>
<span> Hello world! </span><br/>
<span> Hello world! </span>
<br/>
With Pre tag
<pre>
<span> Hello World! </span>
</pre>
<br/>
With Css white-space: pre<br/>
<span style="white-space: pre;">
Hello World! </span>
One of the options is to use a non-breaking whitespace like this const value = ' Hello World!'

JavaScript string: get content of two standing next to each other pieces of content and wrap them together

I'm trying to create a small script that would wrap some parts of text from e.g. <p> tag like this one: <p>... 'displayed text'[popup content] ...</p> in a span wrapper.
The end result would look like this:
<span class='wrapper'>
displayed text
<span class='popup'>popup content</span>
</span>
At the moment I'm able to find and replace the text between apostrophes like this:
some_string.replace(/'(.*?)'/g,'<span>$1</span>');
But I would really like to wrap the popup content part first and then wrap it together with displayed text inside the wrapper element.
Would that be possible?
Sure - how about this?
some_string.replace(/'(.*?)'\[(.*?)\]/, "$1<span class='popup'>$2</span>");
Add a \s* between the two parts of the regex if they could be separated by whitespace:
/'(.*?)'\s*\[(.*?)\]/

Best practice when adding whitespace in JSX

I understand how (and why) to add a whitespace in JSX, but I am wondering what's best practice or if any makes any real difference?
Wrap both elements in a span
<div className="top-element-formatting">
<span>Hello </span>
<span className="second-word-formatting">World!</span>
</div>
Add them on one line
<div className="top-element-formatting">
Hello <span className="second-word-formatting">World!</span>
</div>
Add space with JS
<div className="top-element-formatting">
Hello {" "}
<span className="second-word-formatting">World!</span>
</div>
Because &nbsp causes you to have non-breaking spaces, you should only use it where necessary. In most cases, this will have unintended side effects.
Older versions of React, I believe all those before v14, would automatically insert <span> </span> when you had a newline inside of a tag.
While they no longer do this, that's a safe way to handle this in your own code. Unless you have styling that specifically targets span (bad practice in general), then this is the safest route.
Per your example, you can put them on a single line together as it's pretty short. In longer-line scenarios, this is how you should probably do it:
<div className="top-element-formatting">
Hello <span className="second-word-formatting">World!</span>
<span> </span>
So much more text in this box that it really needs to be on another line.
</div>
This method is also safe against auto-trimming text editors.
The other method is using {' '} which doesn't insert random HTML tags. This could be more useful when styling, highlighting elements, and removes clutter from the DOM. If you don't need backwards compatibility with React v14 or earlier, this should be your preferred method.
<div className="top-element-formatting">
Hello <span className="second-word-formatting">World!</span>
{' '}
So much more text in this box that it really needs to be on another line.
</div>
You can use the css property white-space and set it to pre-wrap to the enclosing div element.
div {
white-space: pre-wrap;
}
I tend to use
It's not pretty but it's the least confusing way to add whitespace I've found and it gives me absolute control over how much whitespace I add.
If I want to add 5 spaces:
Hello <span className="second-word-formatting">World!</span>
It's easy to identify exactly what I'm trying to do here when I come back to the code weeks later.
You can add simple white space with quotes sign: {" "}
Also you can use template literals, which allow to insert, embedd expressions (code inside curly braces):
`${2 * a + b}.?!=-` // Notice this sign " ` ",its not normal quotes.
You can use curly braces like expression with both double quotes and single quotes for space i.e.,
{" "} or {' '}
You can also use ES6 template literals i.e.,
` <li></li>` or ` ${value}`
You can also use &nbsp like below (inside span)
<span>sample text </span>
You can also use &nbsp in dangerouslySetInnerHTML when printing html content
<div dangerouslySetInnerHTML={{__html: 'sample html text: '}} />
I have been trying to think of a good convention to use when placing text next to components on different lines, and found a couple good options:
<p>
Hello {
<span>World</span>
}!
</p>
or
<p>
Hello {}
<span>World</span>
{} again!
</p>
Each of these produces clean html without additional or other extraneous markup. It creates fewer text nodes than using {' '}, and allows using of html entities where {' hello & goodbye '} does not.
You don't need to insert or wrap your extra-space with <span/>. Just use HTML entity code for space -
Insert regular space as HTML-entity
<form>
<div>Full name:</span>
<span>{this.props.fullName}</span>
</form>
use {} or {``} or to create space between span element and content.
<b> {notif.name} </b> <span id="value"> { notif.count }{``} </span>
Despite using this is a neat approach: using the <Fragment> tag to insert HTML inside a variable, which allows the creation of a custom spacer to be used in JSX.
Import { Fragment } ...
import { Fragment } from "react"
Create the variable..
const space = <Fragment> </Fragment>
Note: it can also be done with <span> instead of <Fragment>
Use like so..
return (
<div> some text here {space} and here... </div>
)
If the goal is to seperate two elements, you can use CSS like below:
A<span style={{paddingLeft: '20px'}}>B</span>

Categories

Resources