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.
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.
Share Improve this question edited Oct 9, 2018 at 13:17 Rishav Sharan asked Oct 9, 2018 at 12:48 Rishav SharanRishav Sharan 2,9329 gold badges42 silver badges58 bronze badges 12 | Show 7 more comments3 Answers
Reset to default 9Here'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.
onclick="myFunction()"
oraddEventListener("click", myFunction)
? (Note for the latter you pass the function object itself, not a call to it.) – Robin Zigmond Commented Oct 9, 2018 at 12:52onclick="${myFunction()}
, it runs the code immediately. If I do, onclick="${myFunction}, nothing happens on click. myFunction in both cases islet myFunction = () => { alert('Yo'); }
– Rishav Sharan Commented Oct 9, 2018 at 12:57$
signs, just have a literal string of HTML, includingonclick="myFunction()"
(escaping quotes if needed). Since it seemsmyFunction
is the only function that you ever want to run here. Template literals are a way to embed the values of expressions inside strings, much easier than using literal strings and expressions with+
inbetween them - but for this reason they're only useful if the content might change according to context. – Robin Zigmond Commented Oct 9, 2018 at 13:01Uncaught ReferenceError: myFunction is not defined at HTMLButtonElement.onclick
– Rishav Sharan Commented Oct 9, 2018 at 13:06myFunction
isn't in global scope. In that case thenonClick
won't work at all. Nor willaddEventListener
if it's executed from a<script>
tag that you're inserting on the page. I still don't think a template literal is the way to solve this - I'd say you're better off making theaddEventListener
call just after you've inserted the HTML, and making suremyFunction
is in scope there. Hard to know how to do it without knowing more about your code - but I'm pretty sure this isn't the kind of problem template literals were designed to solve. – Robin Zigmond Commented Oct 9, 2018 at 13:10