Josh Horton
Josh Horton

Reputation: 77

jQuery on click method not being called on array elements

I am printing out an array of products to the screen. There is a delete button being printed along with each product. The code is as follows:-

const output = document.getElementById('output');

function delete_item(){
    var id = $(this).attr('data-id');
    console.log("ID " + id);
}

let productsArray = [];

$.getJSON('/products', products => {
    let outputContent = '';

    productsArray = Object.values(products);

    productsArray.forEach(product => {  
        outputContent += `<div data-id="${ product.ID }">
                          <div id='edit'><i class='fa fa-pencil-square-o' aria-hidden='true'></i></div>
                          <div id='delete'><i class='fa fa-trash-o' aria-hidden='true'></i></div>
                          <div id='product'> <span class='name'> <a href=''>${product.NAME}</a></span>
                          <span class='price'>Price: £${product.PRICE}</span>
                          </div>`;

    });

    $('#delete').click(function(){
        delete_item();
    });

    output.innerHTML = outputContent;
});

Currently, I would just like the delete_item function to print out the correct product id. However, the function is never invoked.

Is my .click() function within the scope of delete div, and why is the click() function not being called when clicking the delete div?

Upvotes: 1

Views: 51

Answers (3)

Death-is-the-real-truth
Death-is-the-real-truth

Reputation: 72299

1. First of all same id for multiple element will not work when it come to jQuery, so convert id to class like below:-

<div class='delete'>

2. Use Event Delegation:-

$(document).on('click','.delete',function(){
  delete_item($(this).parent().attr('data-id')); // pass data-id to function
});

3. Change function like below:-

function delete_item(id){
    console.log("ID " + id);
}

4. Put delete function outside of $.getJSON().

So the full code is now like this:-

const output = document.getElementById('output');

function delete_item(id){ //change in function
    console.log("ID " + id);
}

let productsArray = [];

$.getJSON('/products', products => {
    let outputContent = '';

    productsArray = Object.values(products);

    productsArray.forEach(product => {  
    outputContent += `<div data-id="${ product.ID }">
                        <div id='edit'><i class='fa fa-pencil-square-o' aria-hidden='true'></i></div>
                        <div class='delete'><i class='fa fa-trash-o' aria-hidden='true'></i></div>
                        <div id='product'> <span class='name'> <a href=''>${product.NAME}</a></span>
                        <span class='price'>Price: £${product.PRICE}</span>
                        </div>`;

    }); // changed id to class
    output.innerHTML = outputContent;
});

$(document).on('click','.delete',function(){ // put click functionality outside
  delete_item($(this).parent().attr('data-id')); // pass data-id to function
});

Upvotes: 1

Ionică Bizău
Ionică Bizău

Reputation: 113345

You're adding multiple elements with the same id. The id should be unique in the document. Instead, use a class:

productsArray.forEach(product => {  
    outputContent += `  <div data-id="${ product.ID }">
                        <div class='edit'><i class='fa fa-pencil-square-o' aria-hidden='true'></i></div>
                        <div class='delete'><i class='fa fa-trash-o' aria-hidden='true'></i></div>
                        <div class='product'> <span class='name'> <a href=''>${product.NAME}</a></span>
                        <span class='price'>Price: £${product.PRICE}</span>
                        </div>`;

});

$('.delete').click(function(){
    delete_item($(this).parent().data("id"));
});

This will send the id to the function:

function delete_item(id){
    console.log("ID " + id);
}

Upvotes: 3

Eduard Void
Eduard Void

Reputation: 2714

You have more problems in your concept. The first is the duplicate ID usage and than the click event binding - you should register events to body element to register the event also to newly added elements. Here is a working code:

const output = document.getElementById('output');

function delete_item(id){
  console.log("ID " + id);
}

let productsArray = [];

$.getJSON('/products', products => {
  let outputContent = '';

  productsArray = Object.values(products);

  productsArray.forEach(product => {  
    outputContent += `  <div data-id="${ product.ID }">
                        <div class='edit'><i class='fa fa-pencil-square-o' aria-hidden='true'></i></div>
                        <div class='delete'><i class='fa fa-trash-o' aria-hidden='true'></i></div>
                        <div class='product'> <span class='name'> <a href=''>${product.NAME}</a></span>
                        <span class='price'>Price: £${product.PRICE}</span>
                        </div>`;

});

$('body').on('click', '.delete', function(){
    delete_item($(this).parent().attr('data-id'));
});

output.innerHTML = outputContent;
});

Upvotes: 1

Related Questions