0

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)

OJM
  • 442
  • 5
  • 16
  • Think of it this way: The Template is a package in the IKEA store, if you attach a click handler there, everyone gets the same additional click handler... So... attach the click handler after the package is unpacked and assembled in the buyers house.... import the template in the DOM, **then** set handlers. – Danny '365CSI' Engelman Aug 02 '20 at 09:51
  • @Danny'365CSI'Engelman Thanks for your post. Have updated my post to what I have tried. – OJM Aug 03 '20 at 01:17
  • Your JSFiddle is incomplete, I presume the not included ``script.js`` contains all your element code. – Danny '365CSI' Engelman Aug 03 '20 at 07:38
  • @Danny'365CSI'Engelman All the Javascript code in my JSFiddle is the code from my script.js file – OJM Aug 03 '20 at 19:18

1 Answers1

2

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.

Harshal Patil
  • 17,838
  • 14
  • 60
  • 126