Skip to content
Advertisement

WeakMap with event.target

Edit: turns out nothing is actually wrong with the second snippet (my real code). On one page it works, and on another it doesn’t. Yea for underlying errors.

I’m creating a DOM element and giving that DOM element to a WeakMap as a key. Then, with JQuery event delegation/event listener, I’m trying to retrieve the saved key but it’s returning undefined:

const item = document.createElement("div"), __data = new WeakMap();
__data.set(item, {hello: "123"})
document.body.appendChild(item)

// later on in event delegation
$("div").on("click", function(event) {
const target = event.target, data = __data.get(target);
console.log(data)
// prints undefined

Anyone know what’s wrong or an alternative method to save data for a DOM element that doesn’t have an ID?

Edit: I’m kinda annoyed that the example I made works but my own code doesn’t… (some bits look redundant. This is modeled after my actual code, so not all the missing pieces are here, just pragmatically) but here’s the apparently working code:

const __data = new WeakMap();

function buildingItem() {
  const item = document.createElement("div");
  item.setAttribute("data-action", "delete");
  __data.set(item, {hi: 123});
  return item;
}

function build() {
  const main = document.getElementById("main")
  for (let i = 0; i < 3; i++) {
    const container = document.createElement("div"), attached = document.createElement("div");
    const build = buildingItem(),
      data = __data.get(build);
    build.classList.add("classified");
    data["hello"] = `Item ${i}`
    __data.set(build, data);
    build.innerText = `Item ${i}`
    attached.append(build);
    container.append(attached);
    main.append(container);
  }
}
build()
$(document).on("click", "div.classified[data-action]", function(event) {
const target = event.currentTarget, data = __data.get(target);
console.log(`CTarget Data: ${data["hello"]}`)
})
<div id="main"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Advertisement

Answer

Two possible issues:

  1. target is the innermost element that was clicked. You probably want this or event.currentTarget instead, which is the element on which you hooked the event handler (which may be an ancestor element to target).

  2. Your jQuery code hooks up the click event on all div elements, not just that one, but you only have that one div in the WeakMap. If you click a different div, you’ll naturally get undefined because that other div isn’t a key in the map.

Here’s an example (I’ve added a span within the div we have in the map to demonstrate #1, and also added a second div to demonstrate #2):

const item = document.createElement("div"), __data = new WeakMap();
__data.set(item, {hello: "123"});
document.body.appendChild(item);
item.insertAdjacentHTML("beforeend", "<span>Click me, I'll work</span>");
document.body.insertAdjacentHTML("beforeend", "<div>Click me, I won't work (I'm not a key in the map)</div>");

$("div").on("click", function(event) {
    const target = event.currentTarget, data = __data.get(target);
    console.log("with currentTarget:", data);
    
    // Note that using `event.target` wouldn't hav eworked
    console.log("with target:", __data.get(event.target));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

You’ve mentioned that in your real code you’re using event delegation. currentTarget and this are both fine in that case as well:

// Event delegation
$(document.body).on("click", "div.example", function(event) {
    const data1 = __data.get(event.currentTarget);
    console.log("using currentTarget:", data1);
    const data2 = __data.get(this);
    console.log("using this:", data2);
});

// Adding the relevant `div`
const item = document.createElement("div"), __data = new WeakMap();
__data.set(item, {hello: "123"});
item.className = "example";
item.textContent = "Some text to make div clickable";
document.body.appendChild(item);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement