UPDATE:
Here is a better example;
My code is
let myFunction = () => {
console.log('Yo');
alert('Yo');
}
let About = {
render : async () => {
return /*html*/`
<h1> About </h1>
<button id="myBtn" type="button" >Try it</button>
<script>
document.getElementById("myBtn").addEventListener ("click", ${myFunction})
</script>
`
}
}
export default About;
This transforms to the HTML code;
<div id="page_container" class="container pageEntry">
<h1> About </h1>
<button id="myBtn" type="button">Try it</button>
<script>
document.getElementById("myBtn").addEventListener ("click", () => {
console.log('Yo');
alert('Yo');
})
</script>
</div>
However on clicking on the button, nothing happens;
I am trying to work on a basic vanilla js SPA and I have hit a problem where I am unable to call any functions in my current module from the html code. I am using the es6 modules by specifying in my index.html that script tag is of type="module".
For example, in this code, i have tried both the inline onclick tag attribute as well as adding an event listener (i used one at a time, not together. showing it here just for illustration)
let myFunction = () => {
console.log('Yo');
alert('Yo');
}
let About = {
render : async () => {
return /*html*/`
<h1> About </h1>
<button id="myBtn" type="button" onclick="${myFunction}">Try it</button>
<script>
document.getElementById("myBtn").addEventListener ("click", myFunction()})
</script>
`
}
}
export default About;
and I consume the resultant view as
content.innerHTML = await page.render();
from my main module.
The only way I am able to do this is by having my function call return yet another template containng the actual JS code.
let myFunction = () => {
return `
alert('Yo');
document.getElementById('myBtn').textContent = 'Duh'
`
}
however, this creates a very ugly page where my entire JS code is added inline into the HTML and that I can no longer use double quotes in my js code.
Here's how you can invoke a function in a template literal:
const func = () => 'Hello'
console.log(`${func()} World`)
Figured out my problem with the help of another forum.
"Scripts inserted into innerHTML don't run. You should try splitting the render function into render and onMount - the second one called just after the innerHTML line."
Architecting my app into;
let About = {
render : async () => {
let view = /*html*/
`
<h1> About </h1>
<button id="myBtn" type="button" >Try it</button>
`
return view
},
after_render: async () => {
document.getElementById("myBtn").addEventListener ("click", () => {
console.log('Yo')
alert('Yo')
})
}
}
export default About;
and consuming it as;
content.innerHTML = await page.render();
await page.after_render();
solved my problems.
You can give the onClick a reference to your function, by not providing the () when referencing it. This will tell JavaScript to call the function and attempt to pass it the event's arguments when it gets triggered.
onclick=`${myFunction}`
will get called everytime the element is clicked.
Related
This is an example of something I'd like to understand better syntactically in JSX.
Problem:
This works:
<button
onClick={ !isRecording ? beginRecording : endRecording } >
</button>
and this works:
<button
onClick={ () => { modalPortal.current.open() } } >
</button>
<Modal ref={modalPortal}>
<h1>Congratulations!</h1>
<p>If this modal opened, you find javascript syntax seamless and intuitive</p>
</Modal>
Together, no bueno.
<button
onClick={!isRecording ? () => {modalPortal.current.open();beginRecording} : endRecording } >
</button>
Error:
react-expected-an-assignment-or-function-call-and-instead-saw-an-expression
Detail:
This is inside a function component. isRecording & endRecording etc are are states in an object within the scope of the function component which defines the page I'm on in the app, modalPortal is a reference:
export default function RecordPage()
{
let [audioURL, isRecording, beginRecording, endRecording, timer] = RecorderContext();
const modalPortal = useRef(null);
...
}
I've also tried various permutations of passing this out to a single function that does the conditional evaluation etc
onClick={ doManyThings() } >
With and without arrows, both kinds of brackets and passing in arguments and without, none of it seems to work. I'd love a clear answer from someone knowledgeable!
References to things I've tried that don't work:
Conditional onClick from ternary
Call multiple functions onClick ReactJS
Setting conditional onClick behaviour in React Component
React: Expected an assignment or function call and instead saw an expression
You can move the ternary/branching logic into a single callback function.
<button
onClick={() => {
if (!isRecording) {
modalPortal.current.open();
beginRecording();
} else {
endRecording();
}
}
>
...
</button>
If you want to continue using the ternary though you need to also invoke the beginRecording function. The idea is similar here, based on the condition, return an anonymous function that does a couple things, or return a function reference that does whatever it does.
<button
onClick={!isRecording
? () => {
modalPortal.current.open();
beginRecording(); // <-- also invoke
}
: endRecording
}
>
...
</button>
Try this:
const handleButtonClick = () => {
if (isRecording) {
endRecording()
return
}
modalPortal.current.open()
beginRecording()
}
<button onClick={handleButtonClick} />
Let's say I've got an HTML page that looks somewhat like this
...
<h1>Title</h1>
<button id="myFirstButton">my first button</button>
<button id="mySecondButton" onclick="myClickFunction()">my second button</button>
<script src="myJavascript.js"></script>
...
And the myJavascript.js looks like this
...
window.myClickFunction = myClickFunction;
document.getElementById("myFirstButton").addEventListener("click", () => {
console.log("clicked on first button!");
});
function myClickFunction() {
console.log("clicked on second button!");
}
...
This code works fine. But I've got a couple questions.
What is the difference?
In which cases should I use which approach?
Why does myClickFunction() not work when I don't use the window.myClickFunction = myClickFunction?
When you declare a function myFunction in the global scope, it IS window.myFunction so
window.myClickFunction = myClickFunction; is the same as doing myfunction=myFunction it has no effect whatsoever.
To answer #3, we need to see more code. Perhaps you did NOT declare myClickFunction in global scope but inside an event handler or something
For example
window.addEventListener("load",function() {
function myFunction() { console.log("hello"); }
})
function myFunction1() {
console.log("hello from myFunction1");
myFunction(); // not in window scope
}
myFunction1()
I have this piece of code.
Where the problem I am facing is that is missing a prop which I want to be an id, obtained inside the map function.
Since I am unable to find a way to send the id to the component outside map, I figured I would do this:
This is my render function
render() {
var users = this.state.userList;
const Table = Reactable.Table,
Td = Reactable.Td,
Tr = Reactable.Tr;
if (users.length === 0) {
return <p>loading</p>
}
return (
<div class="maincontainer">
<div className="content-landing">
<Table
className="table"
filterable={['Email']}
itemsPerPage={8}
currentPage={0}
sortable={true}
>
{users.map((row) => {
return (
<Tr className={row.className}>
<Td column="Email">{row.email}</Td>
<Td column="Edit" ><FontAwesomeIcon className="editIcon" onClick={this.showModal(row.id)} icon={faEdit} /></Td> //----THIS.SHOWMODAL IS BEING AUTOEXECUTED WITHOUT ACCOUNTING FOR THE CLICKING
</Tr>
)
})}
</Table>
<EditUserModal show={this.state.showModal} close={this.closeModal} row={this.state.rowId}/> //---I WANT THIS TO RECEIVE A row.id FROM THE ABOVE MAP
</div>
</div>
)
}
I have written a couple comments in the parts where I want to make the changes.
I also thought about putting <EditUserModal> , inside the <Td> , but since its an external npm module it crashes, it only admits text.
So my solution was, to pass the row.id to the showModal function, and try to set is a state from there.
showModal(rowId) {
// console.log("showmodal state before any click")
// console.log(this.state.showModal)
console.log("triggered show modal")
console.log(rowId)
this.setState({
showModal: true,
rowId: rowId
}, () => {
// console.log("clicked show modal")
// console.log(this.state.showModal)
});
}
I think it should work, but since the function has a () , it auto executes without waiting for any click, making my app to crash.
In your code you are executing the function directly: this.showModal(row.id).
You have to use a callBack function to pass row.id something like:
onClick={()=> this.showModal(row.id)}
This should solve your problem.
You can use a callBack function in the onClick like this:
onClick={()=> this.showModal(row.id)}
Or you can define the showModal function like this:
showModal = (rowId) => () => {
...
}
and onClick={this.showModal(row.id)}
For people who does not understand arrow functions, the above solution is similar to this:
function showModal(rowId) {
return function () {
...
}
}
The showModal function returns another function that will be triggered in the onClick event.
Please find out following code:
var ResultComponent = React.createClass({
getInitialState: function () {
// … Some code …….
},
handleClick: function(event) {
// … Some code …….
// Include html (displaying data)
this.constructor.searchResultMethod(para,para1,para2)
},
statics: {
deleteMethod: function(para = ''){
console.log(para);
});
searchResultMethod: function(){
var html = ‘’
loop{
var html += '<button id="button" onClick="'+ResultComponent.deleteMethod(1)+'"> delete </button>';
}
}
render: function() {
return (
<div>
<button className={this.state.classes} id={this.state.execute} onClick={this.handleClick} >Execute</button>
<button className={this.state.classes} id={this.state.save} onClick={this.handleClick}>Save</button>
</div>
);
}
});
here i am redring execute and save . action define in handleClick , in this appending html with action, delete , calling deleteMethod function .
Here i am calling static function deleteMethod into another static function called searchResultMethod but onclick event get fire automatically on loading of page instead of button click.
I am new for Reactjs.
Need solution.
Try ResultComponent.deleteMethod(1) as static method needs to be access on class.
<script>
var proto = Object.create(HTMLElement.prototype);
proto.createdCallback = function() {
this._innerHTML = this.innerHTML;
}
document.registerElement('template-mini', {
prototype: proto
})
</script>
<template-mini id='example1'>
<script type='text/beforeUpdate'>
console.log('hi')
this.name = 'Bob'
</script>
<p>hello {{name}}</p>
</template-mini>
<template-mini id='example2'>
<p>hello</p>
<script type='text/beforeUpdate'>
console.log('hi')
</script>
</template-mini>
<script>
console.log(example1._innerHTML)
console.log(example2._innerHTML)
</script>
I'm developing a custom-element called template-mini https://github.com/zhoukekestar/webcomponents/tree/master/components/template-mini
When i use this template-mini, i need a preprocessor to modify data or add some function that can be used in template. So i have a script typed beforeUpdate, Unfortunately, i had the below issue:
https://bugs.chromium.org/p/chromium/issues/detail?id=502872
What should i do ? I want to get full innerHTML ( the script will be executed by my custom element ).
There are several solutions.
1. If you can, wait for the document to be loaded before registering the <template-mini> custom element. Therefore you'll be sure that the content of the element is fully parsed when createdCallback() is called:
document.addEventListener( 'DOMContentLoaded', function () {
document.registerElement( 'template-mini', { prototype: proto } )
} )
2. Use another tag than <script>, for example <script-mini>. Anyway because of its specific type attribute it won't be interpreted as a normal script element.
3. You can defer the time you'll get the content by using a function like setTimeout() or requestAnimationFrame():
proto.createdCallback= function () {
setTimeout( function ( e ) {
e._innerHTML = e.innerHTML
console.log( e._innerHTML )
}, 0, this )
}
I'd recommend solution 2.