How to display dynamic HTML correctly? - html

I have an object called article that comes from the backend. It contains id, title and description. The description contains HTML data and I want to be parsed as HTML code by browser however, browser treats it as text. So, I am wondering why. And how to ask browser to parse it as HTML?
interface BodyComponentProps {
name: string;
article: article;
}
class BodyComponent extends React.Component<BodyComponentProps> {
public render() {
const art = this.props.article;
return (
/* <!-- Main container --> */
<nav className="level body-container">
{/* <!-- Left side --> */}
<div className="level-left">
<div className="level-item">
<nav className="panel content-block">
<p className="panel-heading">{art.title}</p>
<div className="panel-block">{art.description}</div>
</nav>
</div>
</div>
{/* <!-- Right side --> */}
<div className="level-right">
<div className="level-item sidebar-item">
<SidebarPanel title={this.props.name}/>
</div>
</div>
</nav>
);
}
}
const mapStateToProps = (state: NahjReduxState) => ({
article: state.content.article,
});
export default connect(mapStateToProps)(BodyComponent);

React treats it as text, not HTML, for security reasons. Allowing inserting HTML from the backend means you're opening your site up for cross-site scripting (XSS - https://en.wikipedia.org/wiki/Cross-site_scripting).
Cross-site scripting (XSS) means that malicious scripts can be injected into your website by other people.
However, if you truly want to do this, you can use the dangerouslySetInnerHtml prop. dangerouslySetInnerHtml requires you to pass an object with the key __html (notice the double underscore), and the value is the HTML you want to render.
Example:
<div dangerouslySetInnerHTML={{__html: 'First · Second'}} />
React dangerouslySetInnerHtml docs

Related

Anchor Tag in Next.js

I'm tryin got use an anchor tag in Next.js
I don't get any console errors when I set it up and click the link, but the page does not jump to the id tag.
This issue on github suggests that people need to figure out a lot of custom code to use anchors. That can't be right.
I have:
const links = [
{ label: 'Solutions', href: '#solutions', id: 'solutions' },
]
<NavLink.Desktop key={index} href={link.href} id={link.id}>
{link.label}
</NavLink.Desktop>
I get no errors, but the page does not jump to the label that has an id of 'solutions'.
Does anyone know how to solve this, or where to go for ideas on how - it can't be intented that complex custom code is required to use an anchor tag?
Chakra UI has a Link component
<Link href='https://chakra-ui.com' isExternal>
Chakra Design system <ExternalLinkIcon mx='2px' />
</Link>
If you use the regular anchor tags
<Link href="#anchor_one">Menu one</Link>
<Link href="#anchor_two">Menu two</Link>
Then you can add the id for the anchors to the sections you want to navigate into
<div id="anchor_one" />
<div id="anchor_two" />
This can be either pages or components.
I hope this helped a little bit.
As said by #juliomalves in the comments, you have to specify the id attribute on the element in which you wish to navigate to. Not on the anchor tag.
The id for the anchor should be set on the element you want to link to, not on the link itself.
The below code works for me in Next.js -
export default function Home() {
return (
<div>
Click
<section
style={{ marginTop: "1000px", marginBottom: "1000px" }}
id="section"
>
<h1>Test</h1>
</section>
</div>
);
}
Your code should look like this -
const links = [{ label: 'Solutions', href: '#solutions', id: 'solutions' }]
<NavLink.Desktop
key={index}
href={link.href}
// id={link.id} - This is wrong, as you're referring to the same element
>
{link.label}
</NavLink.Desktop>
// Rather set the id attribute in a separate div/section element
<div id={link.id}>
<h2>Solutions</h2>
</div>
maybe try
const links = [
{ label: 'Solutions', href: '#solutions', id: 'solutions' },
]
<NavLink.Desktop key={index} href={links[0].href} id={links[0].id}>
{link.label}
</NavLink.Desktop>
since you only have 1 element in the links array, if you have multiple just map through the array
It is possible to scroll to anchor programatically using Router.push:
import { useRouter } from 'next/router'
const Foo = () => {
const { push } = useRouter()
const handleClick = () => {
push("#blah")
}
return (
<div>
<button onClick={handleClick}>Scroll</button>
<div>Foo</div>
<div>Bar</div>
<div id="blah">Blah</div>
</div>
)
}
Next.js recognises that you are passing something that is not a link to a new page and will concat it (in the example #blah) to the end of the URL.
Have a read about Link from next/link its a built in feature.
https://nextjs.org/docs/api-reference/next/link
https://github.com/vercel/next.js/blob/canary/examples/hello-world/pages/index.js#L7

HTML not rendered inside tooltip from react-tooltip

I used tooltip form react-tooltip and I want to inside tooltip put some HTML tags. How to manage this? I don't find any information in react-tooltip site.
For now I create Tooltip:
const TooltipConst = props => {
if (props.tooltip && props.id) {
const tooltip = <Tooltip id={props.id + 'Tooltip'}>
<div> render(){props.tooltip} </div>
</Tooltip>;
return (
<OverlayTrigger
overlay={tooltip}
placement="top"
delayShow={500}
delayHide={1000}
>
{props.children}
</OverlayTrigger>
);
}
return <div>{props.children}</div>;
};
And when pass as tooltip some string with HTML they not rendered. Any advice?
I try also put as object, for example <span><p>some text</p> Some text </span>, but it return not text but something like Object[] as tooltip.
If you want to add html in ReactTooltip, like html button or other html tags in it. And wants to show on click.
<div id={row.index} className="text-center">
<a data-tip={'dummystring'} data-event={'click focus'}
data-for={'tooltip'}>Show tooltip</a>
<ReactTooltip id={'tooltip'} effect="solid"
clickable={true} place="right"
getContent={function() {
return (
<div>
<span>Some text</span>
<Button
onClick={()=>alert('clicked')}>
Click Me </Button>
</div>
)
}}/>
</div>
const tooltip = (<Tooltip id={props.id + 'Tooltip'}>
<div> render(){props.tooltip} </div>
</Tooltip>);
this is by their officiel documentation
also if you want to render html through props you should use dangerouslySetHTML => see React's documentation
You can use react-tooltip library.
Pass a prop html={true} to <ReactTooltip /> as <ReactTooltip html={true} /> for more information refer this link
This is an old question but I had a look into the documentation and they now have a data-html prop to detect if you want render html markup, something like this:
<ToolTipData data-tip={text} data-html={text.indexOf('</') > -1}>
{children}
</ToolTipData>
It's not super obvious from the docs but even if you are wanting HTML to be rendered inside the tooltip, it still needs to be in a string (wrap your HTML in backticks). Setting the html prop on the tooltip under the hood sets dangerouslySetInnerHtml on the string you pass in.
const inner = `<p>I'm html in a string</p><p>Same</p>`
and your tooltip:
<ReactTooltip
html={true}
id={"tooltip"}
place="right"
type="dark"
effect="solid"
>
{inner}
</ReactTooltip>

Problem with Styling and Visibility while showing modal in Angular 4 Application --

Facing problem with opening and displaying a modal in my Angular4 .NET Application. I would click a link and consecutively a modal would show. In my case the date link for invoice number [pl see the image].
I followed the approach shown here -- http://jasonwatmore.com/post/2017/01/24/angular-2-custom-modal-window-dialog-box
Now what I have currently is, my opaque screen blocking the background but the modal is not displaying as I was hoping for. Like this
I don't know why the modal didn't appear. I am guessing z-index problem maybe? Cause I do not see any console errors. So probably not angular code related matter. Most likely CSS is what I feel. My main app screen is divided into 2 segments as you can see, col-sm-3 and col-sm-9 body content.
Basically this is what I wrote to test my code.
my main app window layout -
<div class='container-fluid'>
<div class='row'>
<div class='col-sm-3'>
<nav-menu></nav-menu>
</div>
<div class='col-sm-9 body-content'>
<alert-component></alert-component>
<router-outlet></router-outlet>
</div>
</div>
</div>
my modal related html --
<div class="col-md-4" style="border-radius:8px; background:linear-gradient(50deg, #e1ecfa, #f2fbde); text-align:right; margin-left:12px; padding:10px;">
<b style="color:darkblue">Invoices issued to this customer</b>
<ul style="list-style:none" *ngFor="let i of iObj">
<li (click)="openInvoiceModal('custom-modal-1')" class="glyphicon glyphicon-arrow-right">
<a>
<b>{{i.inv_id}}, on {{i.inv_date}}</b>
</a>
</li>
</ul>
</div>
*** my test modal ***
<modal id="custom-modal-1">
<div class="modal">
<div class="modal-body">
<h1>Invoice Modal!</h1>
<p>
Home page text: Hello There!
</p>
<button (click)="closeModal('custom-modal-1');">
Close
</button>
</div>
</div>
<div class="modal-background"></div>
</modal>
typescript with this page --
openInvoiceModal(id: string) {
this.modalService.open(id);
}
closeInvoiceModal(id: string) {
this.modalService.close(id);
}
All the other files and code are the same as has been written in that link/tutorial. I tried experimenting at one place with z-index also. But it didn't serve the purpose. So I am baffled.
A few alterations in the modalcomponent file also according to my layout css etc, so I am posting it here.
export class ModalComponent implements OnInit, OnDestroy {
#Input() id: string;
private element: JQuery;
constructor(private modalService: ModalService, private el: ElementRef) {
this.element = $(el.nativeElement);
}
ngOnInit(): void {
let modal = this;
// ensure id attribute exists
if (!this.id) {
console.error('modal must have an id');
return;
}
this.element.appendTo('.container-fluid');
this.element.on('click', function (e: any) {
var target = $(e.target);
if (!target.closest('.modal-body').length) {
modal.close();
}
});
this.modalService.add(this);
}
// remove self from modal service when directive is destroyed
ngOnDestroy(): void {
this.modalService.remove(this.id);
this.element.remove();
}
open(): void {
this.element.show();
$('.container-fluid').addClass('modal-open');
}
// close modal
close(): void {
this.element.hide();
$('.container-fluid').removeClass('modal-open');
}
}
I am not sure why the modal itself is not showing. Although the opaque background is being called means - I am going the right way. ALMOST!
What am I missing? Where is the glitch? Surely it has to be some small tricky part that I am failing to grab! Kindly guide me.
Let me know if you need more code stubs from me to understand my scenario. I will be happy to share.
In anticipation,

How to recognize response as JSON?

In my ReactJS, I'm making a fetch to an API, and the JSON body response field is the following:
{
"place": <a href=\"http:\/\/place.com\/
search?q=%23MILKYDOG\" target=\"_blank\">#milkydog<\/a>
and quickly came up with a little comic about it. You can
(and should) follow Naomi on twitter <a href=\"http:\/\
/david.com\/ngun\" target=\"_blank\">#ngun<\/a> "
}
And when I try to render it by simply passing the prop down (fetched) to rather than recognizing the formatting and escape characters, and rendering accordingly to them.
What's happening here is that React is helping you out by not allowing random HTML to be injected in to your app. You'll need to use the dangerouslySetInnerHTML way of injecting the content. This is made difficult on purpose because React is trying to help you avoid XSS attacks. So you have to do this the "dangerous" way so you think about whether you could do this without injecting raw HTML (it looks like you're getting content from a blog system maybe? Probably a good example of the exception to the rule.)
From the React documentation, you can use something like the following:
function createMarkup() {
return {__html: 'First · Second'};
}
function MyComponent() {
return <div dangerouslySetInnerHTML={createMarkup()} />;
}
e.g. in your case
var fetchedFile = {
"body": `<p><img src=\"http:\/\/media.tumblr.com\
/tumblr_lh6x8d7LBB1qa6gy3.jpg\"\/><a href=\"http:\/\
/citriccomics.com\/blog\/?p=487\" target=\"_blank\">TO READ
THE REST CLICK HERE<\/a><br\/>\n\nMilky Dog was inspired by
something <a href=\"http:\/\/gunadie.com\/naomi\"
target=\"_blank\">Naomi Gee<\/a> wrote on twitter, I really
liked the hash tag <a href=\"http:\/\/twitter.com\/
search?q=%23MILKYDOG\" target=\"_blank\">#milkydog<\/a>
and quickly came up with a little comic about it. You can
(and should) follow Naomi on twitter <a href=\"http:\/\
/twitter.com\/ngun\" target=\"_blank\">#ngun<\/a> `
};
function createMarkup(html) {
return {__html: html};
}
class MyThing extends React.Component {
render() {
return(
<div dangerouslySetInnerHTML={createMarkup(fetchedFile.body)} />
);
}
}
ReactDOM.render(<MyThing />, document.getElementById('content'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>
<div id="content"></div>
React by default always renders as textNode for javascript variables for security reasons, unless you mention it explicitly.
render() {
return(
<div dangerouslySetInnerHtml={{__html: fetchedFile.body}} />
)
}
Read more on this here

angular 2 include html templates

in angular 2 I need to create a large html-template with redundant parts.
Therefore I want to create multiple html-templates and put them together by including them in the main html-file (like ng-include in angular1)
But how can I include sub-templates in the main-template?
example:
<!-- test.html -->
<div>
this is my Sub-Item
<!-- include sub1.html here-->
</div>
<div>
this is second Sub-Item
<!-- include sub2.html here-->
</div>
-
<!-- sub1.html -->
<div>
<button>I'am sub1</button>
</div>
-
<!-- sub2.html -->
<div>
<div>I'am sub2</div>
</div>
You can create components like sub1 sub2 etc. And On those child components add these html files as template .
On main html call the component selectors respectively. It will work
Let me tell you first of all that ng-include from Angular1.x is not supported by Angular2 so obviously $Compile is not present in Angular2. So, you can go ahead with CRF-ComponentFactoryResolver as shown here to add HTML dynamically with angular context.
DEMO--(CFR) : https://plnkr.co/edit/YdRlULhWQR3L3akAr2eb?p=preview
If your HTML piece has angular context, you should use CFR-ComponentFactoryResolver.
As in sub1.html, you have button, you might want to click it and fire its click event. This can be achieved with CFR as shown below,
You can do lot with CRF. This is probably the easiest example.
#Component({
selector: 'my-app',
template: `
<button (click)="addComponents()">Add HTML (dynamically using CRF)</button>
<h1>Angular2 AppComponent</h1>
<hr>
<div>
<h5>sub1.html goes here</h5>
<div class="container">
<template #subContainer1></template>
</div>
</div>
<hr>
<h5>sub2.html goes here</h5>
<div class="container">
<template #subContainer2></template>
</div>
`,
})
export class App {
name:string;
#ViewChild('subContainer1', {read: ViewContainerRef}) subContainer1: ViewContainerRef;
#ViewChild('subContainer2', {read: ViewContainerRef}) subContainer2: ViewContainerRef;
constructor(
private compFactoryResolver: ComponentFactoryResolver
) {
this.name = 'Angular2'
}
addComponents() {
let compFactory: ComponentFactory;
compFactory = this.compFactoryResolver.resolveComponentFactory(Part1Component);
this.subContainer1.createComponent(compFactory);
compFactory = this.compFactoryResolver.resolveComponentFactory(Part2Component);
this.subContainer2.createComponent(compFactory);
}
}
}