I am trying to create a dynamic link Component that transforms a string in a string with a html anchor.
What I want to obtain is a component that returns this output:
<p>Do you want to search?</p>
I am passing this object to the component
let phrase = {
text : 'Do you want to search?'
linktext : 'to search',
linkurl : 'http://google.com'
}
This is the component I tried but do not work and the html is rendered as a text
function InfoLink(props) {
const q = props.phrase;
const link = "<a href={q.linkurl} >{q.linktext}</a>";
const text = q.text.replace(q.linktext, link);
return (
<p>{text}</p>
);
}
Is there a way to have a html output from the component by using replace?
You can split the text, and output the split text along with a react component for the anchor:
let phrase = {
text : 'Do you want to search?',
linktext : 'to search',
linkurl : 'http://google.com'
}
function InfoLink(props) {
const q = props.phrase;
const link = <a href={q.linkurl}>{q.linktext}</a>;
const [part1, part2] = q.text.split(q.linktext);
return (
<p>{part1}{link}{part2}</p>
);
}
ReactDOM.render(<InfoLink phrase={phrase}/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
You can split your sentence in 3 parts:
text_before_link <a href={q.linkurl}> text_with_link </a> text_after_link
Where...
text_before_link = q.text.substr(0,q.text.indexOf(q.linktext));
text_with_link = q.linktext;
text_after_link = q.text.substr(q.text.indexOf(q.linktext)+q.linktext.length);
Something like that.
The variable link is a JSX Object and you are adding it to an string. So the result will be something like: Do you want [Object][Object]. To solve this problem, you should split the string you want to show and the object and return both.
export default function App (props){
const q = props.phrase;
const link = <a href={q.linkurl}>{q.linktext}</a>;
const text = q.text.split(q.linktext)[0];
return (
<p>{text}{link}</p>
);}
Hope this can help.
Related
Scenario: When the user clicks on it, the data should be passed into someFunction().
<span id="someid" onClick={() => someFunction()} data-video-page="some data" class="dot" />`
I tried using getAttributes(), querySelector() methods until now to get the data from data attributes. But one of them are working, in fact they are returning none.
There is a React.js tag in your question, so I'll assume that this is for using data-set in React.js.
For React.js, this is how data-set can be used if you want to pass the data to some function on a click event. You can also visit the live demo here: stackblitz
const handleClick = (event) => {
// Your data is stored in event.currentTarget.dataset
// Here we get the data by destructuring it
// The name video-page need to change to videoPage for JS rules
const { videoPage } = event.currentTarget.dataset;
console.log(videoPage);
// Result printed: "your data"
// You can also run someFunction(videoPage) here
};
export default function App() {
return (
<button data-video-page="your data" onClick={handleClick}>
TEST
</button>
);
}
A working snippet
const someFunction = console.log;
function App() {
return (
<span id="someid"
onClick={(e) => {
const videoPage = event.target.dataset['videoPage'];
someFunction(videoPage)
}}
data-video-page="some data"
className="dot"
>
click me
</span>
)
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
The data* attribute can be accessed using the getAttribute() method.
Example 1:
var data = document.getAttribute('data*');
Example 2:
var element = document.querySelector('div');
var data = element.getAttribute('data');
I have a mongodb database where I saved raw html in it. I have created a custom attribute in the html called kk-id to mention objects inside the html. I want to replace that particular html tag with an anchor tag.
I figured a way to do it using vanilla javascript, however I was wondering if there was a more efficient reactjs way to do it.
data example
<p>Hello <span kk-id="123">John Doe</span></p>
where John Doe's id is 123 saved in it.
/// react component
import React, { useEffect, useState } from "react";
export default function TestComponent() {
const [html, setHtml] = useState(
`<p>Hello <span kk-id="123">John Doe</span><br /></p>`
);
useEffect(() => {
const span = document.querySelector(`[kk-id]`);
if (span) {
const a = document.createElement("a");
a.href = "/people/john-doe";
a.innerText = span.innerText;
span.parentNode.replaceChild(a, span);
}
}, [html]);
return <div dangerouslySetInnerHTML={{ __html: html }} />;
}
You can use html-react-parser and just do
import parse from "html-react-parser";
...
const newParsedHtml = parse(html, {
replace: ({attribs}) => {
if (domNode.attribs && domNode.attribs.id === "123") {
return <span>dynamic text here</span>
}
}
});
I hope vanilla js is the simplest way to do it. For enhancement purpose you can see this. it will be more readable and reusable.
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'm building a type ahead feature in React.
I have wrapper component that has an array of objects, and it renders item; which's a stateless component.
So, suppose I have const name= 'Hasan'. Which gets parsed to >> const parsedName = Ha<span>san</span>; assuming the term to search for is san.
I have tried dangerouslySetInnerHTML={{ __html: parsedName }} attribute on the parent element, but it didn't work.
With plain html this would be: el.innerHTML = parsedName
The goal is to style the span as desired. Any ideas?
class Test extends React.Component {
render() {
const name = 'san';
const parsedName = name.replace(new RegExp('san', 'ig'), '<span>span</span>');
return (
<div dangerouslySetInnerHTML={{__html: parsedName}}/>
);
}
}
ReactDOM.render(
<Test/>,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container">
</div>
Without code its hard to tell what's wrong. I have created a working snippet here that might help you debug your issue.
Updated the example based on the comment.
I have a ReactClass with name Alert. Its render method returns a div with class alert alert-success or alert alert-error according to the type passed while creating element. I just want to know how to add class based on the type of alert element.
Here is my attempt:
var Alert = ReactClass({
render: function() {
return <div className="alert {this.props.type}">{this.props.message}</div>
}
});
var successAlert = React.createElement(Alert, {
type: 'alert-success'
message: 'Information saved successfully!!'
});
When JSX Template is compiled this.props.type is not converted to the class passed to element. How to achieve this ?
Looks like I have found answer to my question. We can simply do something like this:
var Alert = ReactClass({
render: function() {
return <div className={"alert " + this.props.type}>{this.props.message}</div>
}
});
Just put your classes inside Template evaluators { } in this case. Create your class string based on your props and states.
Hope this is helpful to others.
One way to accomplish this is to have a string which will contain all of your classes and then set it to the Component's className:
var Alert = ReactClass({
var yourClassName = 'alert ';
// Add any additional class names
yourClassName += this.props.type + ' ';
render: function() {
return <div className={yourClassName}>{this.props.message}</div>
}
});
or alternatively you can store your class names in an array and convert it to a class friendly string when you're ready to use it:
var Alert = ReactClass({
var yourClassArray = [];
// Add any additional class names
yourClassArray.push('alert');
yourClassArray.push(this.props.type);
var classString = yourClassArray.join(' ');
render: function() {
return <div className={classString}>{this.props.message}</div>
}
});
Take a look at the classnames package. You can do stuff like this:
className={classNames('alert', `alert-${type}`)}
or
className={classNames({
'alert': true,
'alert-success': success,
'alert-error': error
})
You can use JavaScript template literals
var Alert = ReactClass({
render: function() {
return <div className={`alert ${this.props.type}`}>{this.props.message}</div>
}
});
Your code can be written in following way:
const Alert = ({type, message}) =>
<div className={`alert ${type}`}>{message}</div>
Write in code
className={`form-control-sm d-inline per_player ${"per_player_b_" + index + "_score"}`}
and You will get