How to add Event Listener to Web Component Template Elements

1.8k Views Asked by At

I'm building a Twitter clone with some added features for my portfolio. I'm using Web Component's template tag to create the tweet template and then using importNode to render this into the DOM when the post tweet button is clicked. This works fine.

I added an edit button which should run a function when clicked:

         tweetTemplate.content.querySelector('#button').onclick = () =>{
            createTweetContainer.style.display = "block";
            console.log("edit button clicked");
        }

However, this does not work. The create tweet container should be visible when the button is clicked. I also want the button to be unique to each imported template as the user should be able to edit that specific tweet even though it's the same template.

I've read multiple tutorials on web components, custom elements, shadow DOM etc. But I'm stuck on how to tie it all together for this specific task.

Any help on next steps is appreicated. Thank you.

JS FIDDLE: https://jsfiddle.net/manoj1234/zoL5s10g/12/

Update:

I have now added the event listener to the imported node rather than the template as such:

tweetInstance.querySelectorAll('button')[0].onclick = () =>{
    createTweetContainer.style.display = "block";
    console.log("edit button clicked");
}

But I am now getting this error: Uncaught TypeError: Cannot set property 'onclick' of undefined at HTMLButtonElement.postTweetButton.onclick (script.js:59)

1

There are 1 best solutions below

1
On BEST ANSWER

Just change the sequence of operation. Currently, you are appending to the DOM first and then trying to attach the event handler. Instead, first attach the event handler and then append to the DOM. This is the final version:

tweetInstance.querySelector('#button').onclick = () => {
    createTweetContainer.style.display = "block";
    console.log("edit button clicked");
}

// Then append to the DOM
pinnedTweet.after(tweetInstance);

The reason this happens is when you use importNode, it actually returns an instance of DocumentFragment. The intrinsic property of DocumentFragment is that it gets empty when you attach its children to the actual DOM tree. So, querySelector on fragment has not effect. Thus, the ideal workflow with DocumentFragment is to do all operations first and then finally append to the DOM.