I am working with styled components. I accept an h1 element as a prop from an object which contains a string called title. How can I insert a span element into the string of the object so I could style only this part separately as you would normally do if the text was hardcoded?
export const heroData = {
title: `Finance Data`,
You can use dangerouslySetInnerHTML attribute for adding raw HTML string to HTML.
export const heroData = {
title: "Finance <span style="color: red;">Data</span>"
... ...
<div dangerouslySetInnerHTML={{_html: heroData.title}} />
Related
I'm rendering some paragraphs using React. Inside those paragraphs there should be a span for footnotes. The best I got so far is that it rendered [object Object].
function ArticleItem() {
const articles = [
{
title: "title",
content: [
`Text based on this footnote <span>1</span>`,
`Another argument, here is my source <span>2</span>`
]
}
];
return (
<div className="article-container">
<h3> {articles[i].title} </h3>
{
articles[i].content.map(paragraph => (
<p>
{ paragraph }
</p>
)
}
</div>
);
}
Because you are creating a string with "<span>" instead of creating actual <span> HTML elements. What you are using is named jsx, which converts HTML tags to their corresponding document.createElement() (or similar, which in React has it own way).
If you want the content to be an HTML element and not a string, then create an HTML element:
function ArticleItem() {
const articles = [
{
title: "title",
content: [
<p>Text based on this footnote <span>1</span></p>,
<p>Another argument, here is my source <span>2</span></p>
]
}
];
return (
<div className="article-container">
<h3> {articles[i].title} </h3>
{ articles[i].content.map(paragraph => paragraph) }
</div>
);
}
Notice how I removed the string literal (``) and created an HTML element.
If the article content comes from an API call, then avoid using HTML tags inside strings. That's a bad practice actually. Always create the tags within the render() call and populate them with the API data you received.
Assuming the content array has to be supplied as raw HTML, a common solution is to use the dangerouslySetInnerHTML prop to render that HTML directly. You can introduce that to your <p> elements like this:
articles[i].content.map(paragraph => (
<p dangerouslySetInnerHTML={{ __html: paragraph }} />
))
A few other things to consider; I noticed a missing ) in your code after the <p> element of your map statement which will be causing a syntax error. Also, ensure that i is defined to an index in range of your articles array. Here's an example of each fix applied:
function ArticleItem() {
const articles = [
{
title: "title",
content: [
`Text based on this footnote <span>1</span>`,
`Another argument, here is my source <span>2</span>`
]
}
];
const i = 0;
return (
<div className="article-container">
<h3> {articles[i].title} </h3>
{
articles[i].content.map(paragraph =>
(<p dangerouslySetInnerHTML={{ __html: paragraph }} />)
)
}
</div>
);
}
Here's a working example as well - hope that helps!
I'm parsing an RSS feed using rss-parser, displaying the results in a list.
The data is added to the state as such:
async getJobsData() {
let feed = await parser.parseURL(
"https://weworkremotely.com/categories/remote-design-jobs.rss"
);
this.setState({ data: feed.items });
}
The text fields are easy, as these come in as <pubDate>Mon, 20 May 2019 10:36:42 +0000</pubDate>, and are added to their respective list items using <span key={index}>{data.pubDate}</span>.
The response for images is formatted differently though. It's inserted into the generic content response, as the first item.
title: [...]
pubDate: [...]
content: "<img src="https://we-work-remotely.imgix.net/logos/0015/7503/logo.gif?ixlib=rails-2.1.3&w=50&h=50&dpr=2&fit=fill&auto=compress" alt="Logo.gif?ixlib=rails 2.1" />
How would I extract only the URL (https://we-work-remotely.imgix.net/logos/0015/7503/logo.gif?) from that field?
You can use DOMParser to parse the text representation into a DOM.
The code snippet below will print img.src.
const imgText = `<img src="https://we-work-remotely.imgix.net/logos/0015/7503/logo.gif?ixlib=rails-2.1.3&w=50&h=50&dpr=2&fit=fill&auto=compress" alt="Logo.gif?ixlib=rails 2.1" />`
const doc = new DOMParser().parseFromString(imgText, 'text/html')
console.log(doc.body.firstElementChild.src)
You can use HTML parser e.g. https://www.npmjs.com/package/fast-html-parser and get the src attribute.
I have React component, where I have some dynamic text:
...
let spanLength
return(
<SomeComp>
...
<span>Some static text: {someDynamicText}, {someAnotherText}</span>
...
</SomeComp>
)
How can I get the length of text inside span element to a spanLength variable?
You can add a ref to your span
let spanRef = React.createRef()
...
<span ref={spanRef}>Some static text: {someDynamicText}, {someAnotherText}</span>
Then the text length would simply be spanRef.current.textContent.length
Why not, first, compose the whole string? You can grab its length immediately after, and then render it.
const spanStr = `Some static text: ${someDynamicText}, ${someAnotherText}`;
const spanLength = spanStr.length;
return(
<SomeComp>
...
<span>{spanStr}</span>
...
</SomeComp>
)
I have an HTML element with a data attribute:
Remove
<div data-container>
<p>lorem ipsum<p>
<p data-rem></p>
</div>
1.
in the data-trigger sometimes(not always) I send a value:
I want to gather all elements that have the attribute data-trigger:
document.querySelectorAll(['data-trigger']).forEach(function (trigger, index) {
and for each of this trigger to get the DOM and JSON value and parse it:
dom = trigger
value = JSON.parse(trigger.getAttribute('data-trigger'));
I get the DOM reference but for the value I always get null
By using getAttribute do I call again in the DOM ?
Looping thru data-container search for elements which have the attributes one of the keys found in JSON.parse and set their value, the value of the key.
For example:
<p data-rem>albatros</p>
What is currently stopping your script in its tracks is the selector inside querySelectorAll().
It should be '[data-trigger]', not ['data-trigger'].
After you fix it, you'll be able to get all elements with a data-trigger attribute. However, the string you placed in data-trigger attribute won't parse as a JavaScript object (as you probably expect). Your best bet would be to replace quotes with double quotes and double quotes with quotes, making it a valid JSON string and parse it:
<a href="#" data-trigger='{"rem": "albatros"}'>Remove</a>
JSON.parse(elem.getAttribute('data-trigger')) // where elem is the DOM element above
You haven't been exactly clear on what the purpose of this script is but, assuming you want to find a list of DOM elements having 'data-'+foundKey equal to foundVal, you could make the following selector:
document.querySelectorAll('[data-'+foundKey+'="'+foundVal+'"]').forEach(function(el, i){
console.log(el, i);
})
... but in your case that wouldn't do anything, because you don't have any element with
<x data-rem="albatros"></x>
Here's a working example of what I'm talking about, applied to your markup:
document.querySelectorAll('[data-trigger]').forEach(function (trigger, index) {
const triggerProp = JSON.parse(trigger.getAttribute('data-trigger')),
foundKey = Object.keys(triggerProp)[0],
foundVal = triggerProp[Object.keys(triggerProp)[0]],
targets = document.querySelectorAll('[data-'+foundKey+']').forEach(function(target, index) {
console.log(target, 'key:'+foundKey, 'val:'+target.getAttribute('data-'+foundKey));
});
})
<a href="#" data-trigger='{"rem": "albatros"}'>Remove</a>
<div data-container>
<p>lorem ipsum<p>
<p data-rem="test"></p>
</div>
Do note that it only works because the value of data-trigger is valid JSON. If it were not, it would fail miserably. You could guard your script from this risk by a try/catch function that would test the value as JSON first. Another alternative is to use a library that parses relaxed JSON.
This is not valid JSON String
Remove
Try:
<a href="#" data-trigger='{"rem": "albatros"}'>Remove</a> <!-- Double quotes in JSON -->
Then:
document.querySelectorAll("[data-trigger]").forEach(function (trigger, index) {
var val = JSON.parse(trigger.getAttribute('data-trigger'));
for( key in val){ //Loop through (JSON-)Object
setInnerElements(val[key], key);
}
});
function setInnerElements(val,key){
document.querySelectorAll("[data-container] > [data-"+ key +"]").forEach(function (el, index) {
el.innerHTML = val;
})
}
<a href="#" data-trigger='{"rem": "albatros", "foo":"test1", "bar":"test2"}'>Remove</a>
<div data-container>
<p>lorem ipsum<p>
<p data-rem></p>
<p>lorem ipsum<p>
<p data-foo></p>
<p>lorem ipsum<p>
<p data-bar></p>
</div>
Is it possible to pass HTML tags as properties and then render in React.js
For example ES2015 syntax:
I add the property as a string with HTML tags:
renderItems(posts) {
var groupDate = this.props.item.date.toUpperCase();
var listCol = '<h4>' + groupDate.toString() + '</h4>';
return (<ViewList list={posts} postCol1={listCol}/>);
}
And in my ViewList component I have:
<div className="col-md-9">{this.props.postCol1}</div>
This is rendered as :
<h4>JANUARY 28TH, 2016</h4>
How do I get react to render the date excluding the HTML tags?
Different views uses this component and tags may be different explaining why I would like to include the tag.
This actually worked:
renderItems(posts) {
var groupDate = this.props.item.date.toUpperCase();
return (<ViewList list={posts} postCol1={<h4>{groupDate.toString()}</h4>}/>);
}
Take the <h4> tags out of the listCol string. Your ViewList component should render them:
<div className="col-md-9">
<h4>
{this.props.postCol1}
</h4>
</div>