skip to Main Content

Good afternoon,

I have a deconstructed object and I want to dinamically attribute the id of each object to a created element.

While using the e to listen for clicks, I am being unable to get the proper result because the e.target.dataset.id is returning as undefined.

This is the snippet of code

import { menuArr as menuOptions } from "/data.js"

// handle Clicks
document.addEventListener('click', function (e) {
    if (e.target.classList.contains('plus-btn')) { 
        console.log(e.target.dataset.id);
    }
});

// renders the menu
function renderMenuOpts(options) {
    return options.map(option => {
        const {
            name,
            ingredients,
            id,
            price,
            emoji,
        } = option;
        const ingredientString = ingredients.join(', ');

        return `
        <div class="menu-option">
            <span class="emoji">${emoji}</span>
            <div class="option-details">
                <h3 class="option-name">${name}</h3>
                <p class="list-ingredients">${ingredientString}</p>
                <p class="price">${price}€</p>
            </div>
            <button class="plus-btn" data-id="${option.id}">
                <img src="/images/plus.png" class="plus-btn" alt="Plus icon">
            </button>
        </div>
        `;
    }).join(' ');
}

// render the total Menu 
function addToCashout(optionId) {
    document.getElementById('orderTotal').style.display = 'block';
    console.log(optionId);
}

function render() {
    document.getElementById('selectOptions').innerHTML = renderMenuOpts(menuOptions);
}

render();

Issues with using dataset

2

Answers


  1. Because your button contains an image the event that is being handled is most likely from that element rather than its button parent.

    You could change your handler to reflect this:

    document.addEventListener('click', function (e) {
    
      // Find the button - the closest (ancestor) element -
      // that also has a plus-btn class and then grab _its_
      // dataset instead
      const btn = e.target.closest('button.plus-btn');
      console.log(btn.dataset.id);
    });
    

    Additional documentation

    Working example

    // handle Clicks
    document.addEventListener('click', function (e) {
      const btn = e.target.closest('button.plus-btn');
      console.log(btn.dataset.id);
    });
    
    // renders the menu
    function renderMenuOpts(options) {
        return options.map(option => {
            const {
                name,
                ingredients,
                id,
                price,
                emoji,
            } = option;
            const ingredientString = ingredients.join(', ');
    
            return `
            <div class="menu-option">
                <span class="emoji">${emoji}</span>
                <div class="option-details">
                    <h3 class="option-name">${name}</h3>
                    <p class="list-ingredients">${ingredientString}</p>
                    <p class="price">${price}€</p>
                </div>
                <button class="plus-btn" data-id="${option.id}">
                    <img src="/images/plus.png" class="plus-btn" alt="Plus icon">
                </button>
            </div>
            `;
        }).join(' ');
    }
    
    // render the total Menu 
    function addToCashout(optionId) {
        document.getElementById('orderTotal').style.display = 'block';
        console.log(optionId);
    }
    
    function render() {
        document.getElementById('selectOptions').innerHTML = renderMenuOpts([
        {
                name: 'Name',
                ingredients: ['ingredient'],
                id: 1,
                price: 1,
                emoji: 'emoji',
            },
        {
                name: 'Name2',
                ingredients: ['ingredient1'],
                id: 2,
                price: 100,
                emoji: 'emoji2',
            }]);
    }
    
    render();
    <div id="selectOptions"></div>
    Login or Signup to reply.
  2. This is happening because both your image and your button have a class of plus-btn, and the innermost <img> is capturing the click.

    One way to fix it is to check if there’s a parent element of the target, and see if that’s what you want:

    // handle Clicks
    document.addEventListener('click', function (e) {
        const parent = e.target.parentElement;
        if (parent && parent.classList.contains('plus-btn')) { 
            console.log(parent.dataset);
        }
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search