ceekay
ceekay

Reputation: 466

jQuery on-click event empty

I'm trying to read an attribute in my JavaScript-Function, so I can then further call a DELETE via AJAX with this attribute, but I already fail with retrieving the attribute by, what appears to me as, random. (jQuery version used for that is 3.2.1)

The "button" to start that chain (also already tried without the href and with href="#"):

UPDATE: Since it appeared as a comment, I indeed have something within the a-tag

<a class="btn btn-light delete-record" href="" data-id="5c25f547d42" title="Delete">
    <i class="fa fa-trash"></i>
</a>

My JavaScript:

$(document).ready(function(){
    $('.delete-record').on('click', function(e){
        $target = $(e.target);
        var id = $target.attr('data-id');
        if(confirm('Entry with ID ' + id){
           //AJAX
        }
    });
});

During testing with the confirm, I found out that my ID is sometimes set to undefined. Sadly I have no clue how this sometimes works and shows me the ID, and sometimes not.

Is there a solution to make this work with every click and not only about 24 out of the 42?

Upvotes: 1

Views: 2074

Answers (10)

Shilly
Shilly

Reputation: 8589

The issue is that when you click the icon inside the hyperlink, that the event bubbles up to the click handler. Inside the click handler, event.target will then refer to the icon element, which does not have the data-id attribute.

So the solution is to either:

1) Move the click event onto the icon and then make sure the hyperlink does not have any padding or other CSS styles that make the <a> clickable without also clicking the <i>.

2) Or check for which node was clicked inside the event:

    var $target = $(e.target);
    var id = $target.prop('tagName') === 'I'
        ? $target.parent().attr('data-id')
        : $target.attr('data-id');
    if (!id ) {
        console.error( $target );
        throw new Error( 'cannot find the correct id for target' );
    }
    else {
        var is_correct_id = confirm( 'Entry with ID ' + id );
        if ( is_correct_id ) {
            //createAjaxCall( 'DELETE', 'somePath', id );
        }
    }

There are other methods to find the correct parent element, in case one day you change the structure and the icon is not an immediate child of the hyperlink anymore. But I don't use JQuery anymore, so I'll leave searching for the correct syntax for .findParent( 'a[data-id]' ) up to the implementer.

3) Or as you demonstrate, duplicate the id onto the icon. :)

Upvotes: 2

ceekay
ceekay

Reputation: 466

The answer is actually based on Shilly's comment to the question.

Since I indeed got another element within my a-tag, the target was different depending on where I clicked the link/button. As an easy fix for that, I simply appended the ID to the i-tag as well:

<a class="btn btn-light delete-record" href="" data-id="5c25f547d42" title="Delete">
    <i class="fa fa-trash" data-id="5c25f547d42"></i>
</a>

Upvotes: 1

nrgx
nrgx

Reputation: 387

Use jQuery .data() function:

<a class="btn btn-light delete-record"
     href=""
     data-id="5c25f547d42"
     title="Delete">
        Delete
    </a>


$(document).ready(function () {
        $('.delete-record').on('click', function (e) {
            $target = $(e.target);
            var id = $target.data('id');
            if (confirm('Entry with ID ' + id)) {
                // AJAX
            }
        });
    });

Upvotes: 0

darklightcode
darklightcode

Reputation: 2772

Have a look on my example, it should cover your problem:

$(document).ready(function(){
    // assuming you're adding/removing .delete-record elements you should bind click on body
    $('body').on('click', '.delete-record', function(e){

        e.preventDefault(); // prevent default action

        var id = $(this).attr('data-id') || false; // i removed $target, you don't need it

        if( id !== false ){ // if id exists
           if(confirm('Entry with ID ' + id){
           //AJAX
           }
        }else{ console.log('id is invalid', id, typeof id); }

    });
});

Upvotes: 0

Jos&#233; Moreira
Jos&#233; Moreira

Reputation: 135

Since you are tracking the click you should prevent the default behaviour of the click, so do like this:

$('.delete-record').on('click', function(e){
  e.preventDefault();
  (...)
});

you don't need to use the target, you can get the data attribute directly.

if you want to use a vanilla js approach:

document.addEventListener("DOMContentLoaded", function () {
  //const records = document.querySelectorAll('.delete-record');
  Array.from(document.querySelectorAll('.delete-record')).forEach(elem =>{
    elem.addEventListener('click', function(e){
     //don't do the default link behaviour    
     e.preventDefault();
     const id = this.dataset.id;
    console.log('Entry with ID :' + id);
    //use your jquery here
  });
  })
  
});
<a class="btn btn-light delete-record" href="" data-id="5c215f547d42" title="Delete">link1</a>
  <a class="btn btn-light delete-record" href="" data-id="eeee5c1125f547d42" title="Delete">link2</a>
    <a class="btn btn-light delete-record" href="" data-id="cccc5c25f431547d42" title="Delete">link3</a>
      <a class="btn btn-light delete-record" href="" data-id="bbbbb5c2345f547d42" title="Delete">link4</a>
        <a class="btn btn-light delete-record" href="" data-id="111115c25f547d42" title="Delete">link5</a>

Personally i had some problems with data attributes and jQuery so i try to avoid using jquery for that. So you can use this and use the ajax call with the id on the variable.

Upvotes: 0

Neel Darji
Neel Darji

Reputation: 143

<a class="btn btn-light delete-record" id="btnDelete"  title="Delete">
$(document).ready(function(){
    $('#btnDelete').on('click', function(e){
        e.stopPropagation();
        $target = $(e.target);
        var id = $target.attr('data-id');
        if(confirm('Entry with ID ' + id){
           //AJAX
        }
    });
});

Or you can try

<a class="btn btn-light delete-record" id="btnDelete" href="javascript:DeleteRecord()"  title="Delete">
    <script>
    function DeleteRecord(){
    //Do your code here
    }

</script>

Upvotes: 0

Kalix
Kalix

Reputation: 25

Use event.preventDefault() as first line in your callback function for "click" or you'll be redirected to link or just reloaded.

Upvotes: 0

shellophobia
shellophobia

Reputation: 1

You could try specifying the role of the anchor tag to button. Then you won't have to worry about specifying the href as the anchor tag will be treated as button. https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/button_role

Upvotes: 0

treyBake
treyBake

Reputation: 6558

You should change your JS + HTML to this:

HTML

<button class="btn btn-light delete-record"
        data-id="5c25f547d42"
        title="Delete">
    Click me!
</button>

Your problem with using <a> is that you don't stop the defaul behaviour of the <a> tag - which is a link. It's just refreshing the page (if you leave href blank). Changing it to a button is much better, as it's .. well a button in principle.

jQuery

jQuery(document).ready(function($)
{
    $('.delete-record').click(function()
    {
        let id = $(this).attr('data-id');
        if (confirm('Entry with ID '+ id)) {
            //whatever
        }
    });
})

You don't need to get the target, just use $(this) to get the clicked element's data-attribute. Then carry on script as normal

Upvotes: 0

Mateus Freire
Mateus Freire

Reputation: 1

Did you tried to href="javascript" and also this could return list of elements so try to put the listener using an id like this

<a class="btn btn-light delete-record" id="deleteButton" href="" data-id="5c25f547d42" title="Delete">
$(document).ready(function(){
    $('#deleteButton').on('click', function(e){
        e.stopPropagation();
        $target = $(e.target);
        var id = $target.attr('data-id');
        if(confirm('Entry with ID ' + id){
           //AJAX
        }
    });
});

Upvotes: 0

Related Questions