Reputation: 13
I am having some difficulty with .on() and getting the data-id of a targeted element.
$("#updateTables-0").on(".joinTable").click(function() {
var tableID = $(".joinTable").attr('data-id');
console.log(tableID);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<span id='updateTables-0'>
<li class="list-group-item joinTable" data-id='2' data-toggle="modal" data-target="#tableConnect" >
<div class="users-list-body">
<div>
<h5 class="text-primary">100 pt | Regular</h5>
<p>vs. DeadSaidFred [1500]</p>
</div>
<div class="users-list-action">
<div class="new-message-count" title='Table #4'>4</div>
</div>
</div>
</li>
<li class="list-group-item joinTable" data-id='3' data-toggle="modal" data-target="#tableConnect" >
<div class="users-list-body">
<div>
<h5 class="text-primary">100 pt | Regular</h5>
<p>vs. coronatime [1500]</p>
</div>
<div class="users-list-action">
<div class="new-message-count" title='Table #5'>5</div>
</div>
</div>
</li>
</span>
</ul>
As you can see I have two li list items, one with a data-id
of 2 and one of 3. No matter which one I click, it is only returning the first.
If I was not using $("#updateTables-0").on()
and just instead had $(".joinTable")
I could call $(this)
and it would work perfectly. (Note, using $(this)
for my actual example above with .on()
returns undefined
.)
I am using the .on()
as the list updates via web sockets, and so I need to have it listening to any changes. Without, once the list updates via the socket, the function won't work at all.
Any help appreciated.
Upvotes: 1
Views: 126
Reputation: 253328
As event delegation is required, and your current HTML is invalid – the only valid child of either a <ul>
or <ol>
element is the <li>
– I've delegated the event-handling to the parent <ul>
element (and attached the id
to that element also). This may need to change for your use-case, however; so please do comment if so.
In this case, however, to stick with the jQuery approach the following code works:
// bear in mind that this id now selects the parent <ul>
// we attach the anonymous function as the 'click' event-handler
// of click-events that match the '.joinTable' selector:
$("#updateTables-0").on('click', '.joinTable', function(event) {
// here we use the 'this' Node (the node we bound the event-
// handler to, and retrieve its 'data-id' attribute value
// with the data() method:
const tableID = $(this).data('id');
console.log(tableID);
});
$("#updateTables-0").on('click', '.joinTable', function() {
const tableID = $(this).data('id');
console.log(tableID);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id='updateTables-0'>
<li class="list-group-item joinTable" data-id='2' data-toggle="modal" data-target="#tableConnect">
<div class="users-list-body">
<div>
<h5 class="text-primary">100 pt | Regular</h5>
<p>vs. DeadSaidFred [1500]</p>
</div>
<div class="users-list-action">
<div class="new-message-count" title='Table #4'>4</div>
</div>
</div>
</li>
<li class="list-group-item joinTable" data-id='3' data-toggle="modal" data-target="#tableConnect">
<div class="users-list-body">
<div>
<h5 class="text-primary">100 pt | Regular</h5>
<p>vs. coronatime [1500]</p>
</div>
<div class="users-list-action">
<div class="new-message-count" title='Table #5'>5</div>
</div>
</div>
</li>
</ul>
This can, as can all jQuery approaches, be rewritten into plain native JavaScript:
// here we use document.querySelector() to retrieve the
// HTMLElement Node that matches the CSS selector:
const delegationTarget = document.querySelector('#updateTables-0');
// here we use addEventListener() to bind the anonymous
// Arrow function as the event-handler for the 'click'
// event:
delegationTarget.addEventListener('click', (evt) => {
// using evt.target to find the element upon which
// the click event was initially fired; using
// closest() to navigate to the ancestor <li>
// of that clicked-element; and using the
// HTMLElement.dataset API to recover the attribute-
// value of the 'id' property (or to recover the
// attribute-value of the data-id attribute, if you
// prefer):
const tableID = evt.target.closest('li').dataset.id;
console.log(tableID);
});
const delegationTarget = document.querySelector('#updateTables-0');
delegationTarget.addEventListener('click', (evt) => {
const tableID = evt.target.closest('li').dataset.id;
console.log(tableID);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id='updateTables-0'>
<li class="list-group-item joinTable" data-id='2' data-toggle="modal" data-target="#tableConnect">
<div class="users-list-body">
<div>
<h5 class="text-primary">100 pt | Regular</h5>
<p>vs. DeadSaidFred [1500]</p>
</div>
<div class="users-list-action">
<div class="new-message-count" title='Table #4'>4</div>
</div>
</div>
</li>
<li class="list-group-item joinTable" data-id='3' data-toggle="modal" data-target="#tableConnect">
<div class="users-list-body">
<div>
<h5 class="text-primary">100 pt | Regular</h5>
<p>vs. coronatime [1500]</p>
</div>
<div class="users-list-action">
<div class="new-message-count" title='Table #5'>5</div>
</div>
</div>
</li>
</ul>
References:
<li>
.<ol>
.<ul>
.document.querySelector()
.Element.closest()
.Event
interface.EventTarget.addEventListener()
.HTMLElement.dataset
API.click()
.closest()
.on()
.Upvotes: 1
Reputation: 3241
You're using a <span>
as a direct child element of the <ul>
, this is invalid HTML. To fix this, you could assign the id
directly to the <ul>
element:
<ul id='updateTables-0'>
<li class="list-group-item joinTable" data-id='2' data-toggle="modal" data-target="#tableConnect">
<div class="users-list-body">
<div>
<h5 class="text-primary">100 pt | Regular</h5>
<p>vs. DeadSaidFred [1500]</p>
</div>
<div class="users-list-action">
<div class="new-message-count" title='Table #4'>4</div>
</div>
</div>
</li>
<li class="list-group-item joinTable" data-id='3' data-toggle="modal" data-target="#tableConnect">
<div class="users-list-body">
<div>
<h5 class="text-primary">100 pt | Regular</h5>
<p>vs. coronatime [1500]</p>
</div>
<div class="users-list-action">
<div class="new-message-count" title='Table #5'>5</div>
</div>
</div>
</li>
</ul>
And then use event delegation to capture each <li>
of the unordered list:
$("#updateTables-0").on("click", "li", function() {
const $li = $(this)
console.log(`data-id of list item: ${ $li.attr('data-id') }`)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id='updateTables-0'>
<li class="list-group-item joinTable" data-id='2' data-toggle="modal" data-target="#tableConnect">
<div class="users-list-body">
<div>
<h5 class="text-primary">100 pt | Regular</h5>
<p>vs. DeadSaidFred [1500]</p>
</div>
<div class="users-list-action">
<div class="new-message-count" title='Table #4'>4</div>
</div>
</div>
</li>
<li class="list-group-item joinTable" data-id='3' data-toggle="modal" data-target="#tableConnect">
<div class="users-list-body">
<div>
<h5 class="text-primary">100 pt | Regular</h5>
<p>vs. coronatime [1500]</p>
</div>
<div class="users-list-action">
<div class="new-message-count" title='Table #5'>5</div>
</div>
</div>
</li>
</ul>
Upvotes: 0
Reputation: 1529
Use jQuery's inner $(this) object inside click callback.
$("#updateTables-0 .joinTable").on("click",function() {
var tableID = $(this).attr('data-id');
console.log(tableID);
});
https://medium.com/@sak1986/event-binding-in-jquery-daf902be7c58
Upvotes: 1