Grandizer
Grandizer

Reputation: 3025

Vue 2 - Click Event - Access data Attributes using jQuery

I have done quite a bit of searching with no luck. That is, until a moment ago when I found @texelate's comment here.

I am rewriting a page written in KnockouJS. Basically, I had (in KO version) added attributes to certain parent elements. Like data-user-id="3" on the outer most element. Then say data-project-id="x" for each set of data within the outer parent. Then, within the data row, on a click event I would simply use jQuery like:

var UserID = $(event.target).closest("table[data-user-id]").data("userId");
var ProjID = $(event.target).closest("tr[data-project-id]").data("projectId");

That worked great. This does not seem to work in Vue on its click event.

From what I gather, this is no longer possible. I liked the prior way, because there was no duplication of the UserID nor ProjectID.

It seems like I have to duplicate now and always pass UserID and ProjectID into my event via code?

I am not looking to change anything, it is really just to know exactly who and what I am working with.

UPDATE

editUsersTime: function (event, isReady) {
  var theDate = $(event.currentTarget).data("date");
  var prjRole = $(event.currentTarget).data("projectAndRole");
  var userID = isReady === true ? this.SelectedReadyUserID :  this.SelectedNotReadyUserID;
  alert("Date: " + date + "\nPR&: " + prjRole + "\nUserID: " + userID);
}

I read that currentTarget is to be used over target. Neither worked.

The alert above returns undefined for both the theDate and prjRole.

When I pass in all of the values it works:

<span v-on:dblclick="editUsersTime($event, true, d, ep.projectID + '|' + ep.projectRoleID)">{{ UserReadyDaily(ep.projectID, ep.projectRoleID, d) | numeric(2) }}</span>

Here is the Event:

editUsersTime: function (event, isReady, date, prjRole) {
  var userID = isReady === true ? this.SelectedReadyUserID : this.SelectedNotReadyUserID;
  alert("Date: " + date + "\nPR&: " + prjRole + "\nUserID: " + userID);
}

If this is the way it has to be then ok. If there is a way that is less repetitive, that would great.

UPDATE 2

While getting some more sample code together, which was basically reverting my code to what it was, most of it worked. WTF. I did reboot last night, but this is javascript, I can't imagine that did anything different. But here is more code:

<table v-if="SelectedNotReadyUserID > 0" v-bind:data-user-id="SelectedNotReadyUserID" class="table table-sm table-bordered table-hover-blue bottomless table-footer-total scrollable">
  <thead>
    ...
  </thead>
  <tbody>
    <tr v-for="ep in SelectedNotReadyUser.distinctUserProjectsAndRoles" v-bind:data-project-id="ep.projectID" v-bind:data-project-and-role="ep.projectID + '|' + ep.projectRoleID" v-bind:class="{ 'is-universal': ep.isUniversal }">
      <td>
        <cite> {{ ep.clientName }}</cite>
        <span class="float-right ml-2">
          <span> {{ ep.projectNumber }}</span>
          <a href="#" v-bind:data-user-name="SelectedNotReadyUser.firstAndLast" v-bind:data-project-number="ep.projectNumber" v-on:click="doInvoiceUser" target="invoice" title="Click to Generate an Invoice based on this Pay Period, Project and User"><i class="far fa-list-alt hand"></i></a>
        </span>
        <br />
        <span> {{ ep.projectName }}</span>
        <span class="float-right ml-1"> {{ ep.projectRole }}</span>
      </td>
      <td v-for="d in DisplayDates" v-bind:data-date="d" v-bind:class="{ canedit: !IsWeekday(d) }" class="text-right">
        <!-- This is the event -->
        <span v-on:dblclick="editUsersTime($event, false)">{{ UserDaily(ep.projectID, ep.projectRoleID, d) | numeric(2) }}</span>
      </td>
      <td class="text-right bold">
        {{ UserProjectTotal(ep.projectID, ep.projctRoleID) | numeric(2) }}
      </td>
    </tr>
  </tbody>
</table>

Here is the event:

editUsersTime: function (event, isReady) {
  console.log("target: " + event.target);
  console.log("currentTarget: " + event.currentTarget);
  var userID = $(event.target).closest("table[data-user-id]").data("userId")
  var parid = $(event.target).closest("tr[data-project-and-role]").data("projectAndRole");
  var datea = $(event.target).closest("td[data-data]").data("date"); // Did not work
  var dateb = $(event.target).parent().data("date"); // Worked
  ...
}

The console was this:

target: [object HTMLSpanElement]
currentTarget: [object HTMLSpanElement]

I am not really sure why datea didn't work, but seeing it was the span, parent did the trick.

Upvotes: 0

Views: 501

Answers (1)

Las Ten
Las Ten

Reputation: 1175

OK, this is just a suspicion, but Vue triggers the events for child elements too. In those cases the event.target is the child element, not the one you specified the event handler for. So for example when you have

<div @click="doThis">
    <span>Click me</span>
</div>

and you click on the span element, the doThis method is called but with the span and not with the div. I think you just have your data attributes on the wrong elements.

Try to log your event target to the console to see what you're getting there.

Upvotes: 1

Related Questions