最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Adding event listeners to elements cloned from the template tag - Stack Overflow

programmeradmin5浏览0评论

I am creating a lot of DOM elements (each has the same HTML structure) with the <template> tag:

<template id="weapon-template">
    <div class="button">
        <div class="button-price"  data-price ></div>
        <img class="button-image"  data-image >
        <div class="button-name"   data-name  ></div>
        <div class="button-damage" data-damage></div>
        <div class="button-amount" data-amount></div>
    </div>
</template>

... and a few lines of JavaScript:

var clone;
var template = document.getElementById( "weapon-template" );

template.content.querySelector( "[data-image]"  ).src = data.prev;
template.content.querySelector( "[data-price]"  ).innerHTML = data.cost + "$";
template.content.querySelector( "[data-name]"   ).innerHTML = data.name;
template.content.querySelector( "[data-damage]" ).innerHTML = data.damage;
template.content.querySelector( "[data-amount]" ).innerHTML = 0;

clone = document.importNode( template.content, true )
this.container.appendChild( clone );

I would love to add some event listeners on the cloned elements. I could not find nothing from internet and tired a couple of things my self, like:

template.content.querySelector( "[data-price]" ).addEventListener( "click", action, false );
clone.querySelector( "[data-price]" ).addEventListener( "click", action, false );

... none of these worked. I could simply do something like:

var child  = this.container.childNodes[ 0 ];
var target = child.querySelector( "[data-price]" );

target.addEventListener( "click", action, false );

... but I wonder if there is another, simpler way similar to those that has not worked for me.

I am creating a lot of DOM elements (each has the same HTML structure) with the <template> tag:

<template id="weapon-template">
    <div class="button">
        <div class="button-price"  data-price ></div>
        <img class="button-image"  data-image >
        <div class="button-name"   data-name  ></div>
        <div class="button-damage" data-damage></div>
        <div class="button-amount" data-amount></div>
    </div>
</template>

... and a few lines of JavaScript:

var clone;
var template = document.getElementById( "weapon-template" );

template.content.querySelector( "[data-image]"  ).src = data.prev;
template.content.querySelector( "[data-price]"  ).innerHTML = data.cost + "$";
template.content.querySelector( "[data-name]"   ).innerHTML = data.name;
template.content.querySelector( "[data-damage]" ).innerHTML = data.damage;
template.content.querySelector( "[data-amount]" ).innerHTML = 0;

clone = document.importNode( template.content, true )
this.container.appendChild( clone );

I would love to add some event listeners on the cloned elements. I could not find nothing from internet and tired a couple of things my self, like:

template.content.querySelector( "[data-price]" ).addEventListener( "click", action, false );
clone.querySelector( "[data-price]" ).addEventListener( "click", action, false );

... none of these worked. I could simply do something like:

var child  = this.container.childNodes[ 0 ];
var target = child.querySelector( "[data-price]" );

target.addEventListener( "click", action, false );

... but I wonder if there is another, simpler way similar to those that has not worked for me.

Share Improve this question asked Jun 21, 2015 at 19:13 user2518044user2518044 5
  • Why are you selecting by data-* attributes? – user3117575 Commented Jun 21, 2015 at 19:18
  • @Jamen Simply because I don't want any id duplicates. – user2518044 Commented Jun 21, 2015 at 19:22
  • 1 @Jamen Class names can change at any time, for example when I'll design some new buttons and with a different HTML structure, etc. In this case data-* attributes are juste like id's, so I can separate the JS functionality from the CSS design. – user2518044 Commented Jun 21, 2015 at 19:28
  • I think name would be a more semantic attribute for, well, naming elements in a template. – PA. Commented Oct 26, 2020 at 6:49
  • Does this answer your question? adding event listener on a dom element inside template tag – Wicket Commented Sep 2, 2022 at 14:54
Add a ment  | 

2 Answers 2

Reset to default 11

Until you 'activate' template using document.importNode, its content are inert nodes which are not part of DOM.

As per addEventListener docs:

The event target may be an Element in a document, the Document itself, a Window, or any other object that supports events (such as XMLHttpRequest).

Therefore adding event listeners in your example won't work until you clone template contents and add them to an existing node in document.

If you are ready to use jQuery, there is a workaround. You can use event delegation using jquery on method to bind events to parent element.

something like this:

$(this.container).on('click', '[data-price]', action);

What this will essentially do that any click which is being triggered from children of this.container will bubble up till parent. If it satisfies the selector criteria of [data-price] action will triggered on it.

If you can get around using a for your list rows, then your document.getElementById(...) will return an actual DOM element instead of just the DocumentFragment that it does right now. This means that importNode(...) will return you real DOM nodes on which you can call addEventListener and hook up events!

发布评论

评论列表(0)

  1. 暂无评论