this is my svelte component code
<script>
export let canCascade = true;
let show = true;
function cascade() {
if (canCascade) {
show = !show;
}
}
</script>
{#if show}
<div class="shade" on:click|self={cascade}>
shade
</div>
{/if}
When I use the component as <Component canCascade=false /> the 'if block' doesn't work.
But hard-coding the value inside just works fine.
Am I missing something here - some conceptual error?
Like #Corrl pointed out in the comments, you need to use {brackets}. If you don't, the variable will follow the rules of an html attribute.
Working repl https://svelte.dev/repl/d13df678eab243e9a13fb705da197219?version=3
In Svelte when we want to pass JavaScript value / expression to an attribute of a component we need to wrap the value / expression with curly brackets {}.
Otherwise, it will be used as a string.
As an example, take a look at the following code:
Component.svelte:
<script>
export let test = true;
$test: console.log(`typeof test = ${typeof test}`);
</script>
App.svelte:
<script>
import Component from "./Component.svelte";
</script>
<Component test=true />
<div />
When you will open the console inside the browser developer tools,
the output will be:
typeof test = string
I have several text boxes and a save button
Each text box value is loaded using the following approach
{
this.getElement('test3lowerrangethreshold', 'iaSampling.iaGlobalConfiguration.test3lowerrangethreshold',
enums.IASamplingGlobalParameters.ModerationTest3LowerThreshold)
}
private getElement(elementid: string, label: string, globalparameter: enums.IASamplingGlobalParameters): JSX.Element {
let globalParameterElement =
<div className='row setting-field-row' id={elementid}><
span className='label'>{localeHelper.translate(label)}</span>
<div className="input-wrapper small">
<input className='input-field' placeholder='text' value={this.globalparameterhelper.getDataCellContent(globalparameter, this.state.globalParameterData)} />
</div>
</div>;
return globalParameterElement;
}
Helper Class
class IAGlobalParametesrHelper {
public getDataCellContent = (globalparameter: enums.IASamplingGlobalParameters, configdata: Immutable.List<ConfigurationConstant>) => {
return configdata?.find(x => x.key === globalparameter)?.value;
}
}
This works fine. Now the user is allowed to update these text values.And on click of save the changes should be reflected by calling a web api .
I have added an onlick event like this
<a href='#' className='button primary default-size' onClick={this.saveGlobalParameterData}>Save</a>
Now inorder to save the data i need a way to identify the text element which has changed.For that i have added an update method within the Helper class
public updateCellValue = (globalparameter: enums.IASamplingGlobalParameters, configdata: Immutable.List<ConfigurationConstant>,updatedvalue:string) => {
let itemIndex = configdata.findIndex(x => x.key === globalparameter);
configdata[itemIndex] = updatedvalue;
return configdata;
}
and return the updated configdata ,and i plan to call this method in the onchange event of every text box like this
<input className='input-field' placeholder='text' onchange={this.setState({ globalParameterData: this.globalparameterhelper.updateCellValue(globalparameter, this.state.globalParameterData, (document.getElementById(elementid) as HTMLInputElement).value})}
But this does not seem like a correct approach as there are number of syntactical errors. I initially got the data using an actioncreator like this.Please advice.
samplingModerationActionCreator.getGlobalParameters();
samplingModerationStore.instance.addListener(samplingModerationStore.SamplingModerationStore
.IA_GLOBAL_PARAMETER_DATA_GET_EVENT,
this.getGlobalParameterData);
}
I want to make id like this dynamically.
<div id="track_1"></div>
<div id="track_2"></div>
So I gave the id like this from parent component.
export default function Components(props) {
return (
<AudioTrack trackNum="1"/>
<AudioTrack trackNum="2"/>
)
}
then in my AudioTrack Component I got the trackNum and want to use like this
const AudioTrack = (props) => {
return(
<div id="track_{props.trackNum}" ></div>
);
}
Howeber it doesn't work.
Is there any good way?
Since the div prop isn't a constant string, you need {} to indicate an expression, and then either use + to concatenate or a template literal with ${}:
<div id={`track_${props.trackNum}`}></div>
I crated a react html element like:
let elements = (
<div>
<div>dwewe</div>
<div>wefwef</div>
<span>yurhfjer</span>
</div>
);
and now I wanted to pass this to an html attribute, hence I converted the react element into string using:
<span data-tip-react={ReactDOMServer.renderToString(element)}>{title}></span>
I'm now able to access these elements, however I'd like to convert it back to react element (the way it was before conversion)
here is what I'm expecting the o/p as:
I tried using DOMParser, however it returned an html element that React did not accept for rendering and threw an errr: not a react element
How do I convert the string back into the same format - React element??
please help!
thanks
Following here :
dynamic HTML String to react component
You can use dangerouslySetInnerHTML (for simple element) or some npm package :
class App extends Component {
constructor() {
super();
this.state = {
name: 'React'
};
}
getDom() {
return (
<div>
<div>dwewe</div>
<div>wefwef</div>
<span>yurhfjer</span>
</div>
);
}
convertToString(dom) {
console.log("To String", ReactDOMServer.renderToString(dom))
return ReactDOMServer.renderToString(dom)
}
convertToDOM(string) {
let domparser = new DOMParser();
console.log("To Dom", domparser.parseFromString(string, 'text/html'))
return domparser.parseFromString(string, 'text/html')
}
render() {
return (
<div>
<Hello name={this.state.name} />
<p>
Start editing to see some magic happen :)
{<div dangerouslySetInnerHTML={{__html: this.convertToString(this.getDom())}}></div>}
</p>
</div>
);
}
}
ex : https://stackblitz.com/edit/react-mhsqfd
i have read some of pug documentation. its said that i have to install pug first and i'm already done that. then i have to require pug in my js file.
but i don't know where to write the compile for pug file in my react files? what is the right steps to use pug in react framework?
thanks! i really appreciated any help.
here is one of my component in react that i would like to render it with pug.
import React from 'react';
import Sidebar from './Sidebar';
import Header from './header/Header';
import {tokenverify} from '../../utils/helpers';
import pug from 'pug';
class Home extends React.Component {
componentDidMount() {
const token = localStorage.getItem('token')
tokenverify(token)
.catch((res) => {
this.props.history.push('/')
})
}
render() {
return(
<div className="main-container">
<div className="col-md-1">
<Sidebar history={this.props.history} username={this.props.params.username}/>
</div>
<div className="col-md-11">
<div className="row">
<Header history={this.props.history} username={this.props.params.username} />
</div>
<div className="row">
{this.props.children}
</div>
</div>
</div>
)
}
}
export default Home
I found this project in very early phase of its development : https://github.com/bluewings/pug-as-jsx-loader.
I like it because it lets me write my dumb (presentational) react components as pug templates.
The only JSX functionality it currently supports are iterating and conditional if. Which seems good enough for writing most of the dumb components.
Here are the steps to use it
1. Install pug-as-jsx-loader
npm install pug-as-jsx-loader --save-dev
For next step you will have to eject if you are using create-react-app
2. Tell webpack how to handle pug templates.
In your webpack.config.dev.js,
{ test: /\.pug$/, use: [require.resolve('babel-loader'), require.resolve('pug-as-jsx-loader')] },
3. Import pug template in your component
import myTemplate from './mycomponent.pug'
4. Return compiled template from render function
const MyComponent = ({someProperty, someOtherProperty})=> {
return myTemplate.call({}, {
someProperty,
someOtherProperty
});
};
5. Define a pug to render component
#my-element
ul.my-list
li(key='{something.id}', #repeat='something as someProperty')
div(className='planet') {something.name}
div(className='vehicle') {something.type}
div(className='overview') {something.cost}
div(className='cancel', onClick='{()=> someOtherProperty(something)}')
div(className='no-mobile fa fa-remove')
A read about my experience : https://medium.com/p/7610967954a
With Pug, you have two options: render template to HTML string, passing the data object right away or render template to an efficient javascript function that outputs html when passed a data object.
When using pug(alone) with dynamic data, the choice is obviously to compile to function, so that data can be applied on the client.
However, React does not actually consume, or send to the client, html.
If you read an explanation of JSX, you will see that it is just HTML-lookalike syntactic sugar that gets compiled to a javascript function that programmatically creates DOM nodes (essential for the way React handles diffing and updating the page). Pug at the moment, even on the client, outputs an HTML string. Hence, the only way we will be able to use it is
dangerouslySetInnerHTML as following:
//from https://runkit.io/qm3ster/58a9039e0ef2940014a4425b/branches/master?name=test&pug=div%20Wow%3A%20%23%7Ba%7D%23%7Bb%7D
function pug_escape(e){var a=""+e,t=pug_match_html.exec(a);if(!t)return e;var r,c,n,s="";for(r=t.index,c=0;r<a.length;r++){switch(a.charCodeAt(r)){case 34:n=""";break;case 38:n="&";break;case 60:n="<";break;case 62:n=">";break;default:continue}c!==r&&(s+=a.substring(c,r)),c=r+1,s+=n}return c!==r?s+a.substring(c,r):s}
var pug_match_html=/["&<>]/;
function pug_rethrow(n,e,r,t){if(!(n instanceof Error))throw n;if(!("undefined"==typeof window&&e||t))throw n.message+=" on line "+r,n;try{t=t||require("fs").readFileSync(e,"utf8")}catch(e){pug_rethrow(n,null,r)}var i=3,a=t.split("\n"),o=Math.max(r-i,0),h=Math.min(a.length,r+i),i=a.slice(o,h).map(function(n,e){var t=e+o+1;return(t==r?" > ":" ")+t+"| "+n}).join("\n");throw n.path=e,n.message=(e||"Pug")+":"+r+"\n"+i+"\n\n"+n.message,n}function test(locals) {var pug_html = "", pug_mixins = {}, pug_interp;var pug_debug_filename, pug_debug_line;try {;var locals_for_with = (locals || {});(function (a, b) {;pug_debug_line = 1;
pug_html = pug_html + "\u003Cdiv\u003E";
;pug_debug_line = 1;
pug_html = pug_html + "Wow: ";
;pug_debug_line = 1;
pug_html = pug_html + (pug_escape(null == (pug_interp = a) ? "" : pug_interp));
;pug_debug_line = 1;
pug_html = pug_html + (pug_escape(null == (pug_interp = b) ? "" : pug_interp)) + "\u003C\u002Fdiv\u003E";}.call(this,"a" in locals_for_with?locals_for_with.a:typeof a!=="undefined"?a:undefined,"b" in locals_for_with?locals_for_with.b:typeof b!=="undefined"?b:undefined));} catch (err) {pug_rethrow(err, pug_debug_filename, pug_debug_line);};return pug_html;}
// pug source: "div Wow: #{a}#{b}"
// this would obviously be much shorter if you include pug-runtime globally in your application
function createMarkup(a,b) {
return {__html: test({a:a,b:b})};
}
function MyComponent(props) {
return <div dangerouslySetInnerHTML={createMarkup(props.a, props.b)}/>;
}
ReactDOM.render(
<MyComponent a="banana" b="&patata"/>,
document.getElementById('root')
)
<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=root />
Alternatively, there are attempts to translate jade or pug syntax into react directly, such as pug-react-compiler and babel-plugin-transform-pug-to-react. It seems they solved including further react components inside the pug template, which might be a desirable tradeoff for them possibly having quirks.