1

I have an ASP.NET project that is effectively a single page application, it utilises both razor and Javascript to render the page and provide user control.

Within my application there are a number of task structures that each have their own independent ID, these tasks are presented to the user within a list. As part of providing user control there are a number of buttons for each task that allow the user to do certain things; such as completing a task.

Since there are multiple tasks on a single page there needs to be a way of identifying one task from another, this is done through the taskId, which is mentioned before. For example a "Complete" button will contain a custom attribute data-taskId, which can be then retrieved and passed on to a Javascript function for use.

However my issue is with actually providing the Javascript function with the taskId in the first place. I am using jQuery, which provides on click functionality through .on("click"). This means that I might have a function something like the below.

$(".complete-button").on("click",
        function (event) {
           //1. get taskId
           //2. complete the task with taskId 
        });

Therefore all of my complete buttons that have the class .complete-button will be able to execute this function. Each task has its own complete button and I want the button to be able to complete only the task it is associated with.

I need to know what is the best way to provide this function with the taskId that is needs to operate properly. Some of the other code within this project written by another programmer makes use of hidden <input> elements that store data within the html page, this data can then be retrieved by jQuery and used within a function. Below is an example of what this would look like:

HTML

<input type="hidden" class="case-status" value="@Model.Status" />

JS

$(".status-button").on("click",
            function (event) {
               var status = $(".case-status").val();
               //2. do something with status 
            });

However this not work, as there is no way to set one of these variables beforehand due to several tasks being presented to the user at once. Since there are several tasks, there can't be one single element holding the current task, since the user could click any of the complete buttons on any of the tasks.

Instead I need a way to retrieve the data-taskId value from the complete button and push it through to the complete button's onClick function, I'm not sure how to do this and also adhere with good practice.

Jake12342134
  • 1,539
  • 1
  • 18
  • 45

2 Answers2

1

You kind of answered your own question:

a "Complete" button will contain a custom attribute data-taskId

To fetch that information in the click event, just grab that data attribute from the clicked element:

$(".complete-button").on("click",
    function (event) {
       let taskId = $(this).data('taskId');
       //2. complete the task with taskId 
    });

In the event handler, this refers to the DOM element triggering the event. Any information stored in that element, any DOM traversal relative to that element, etc. can all be performed from this.

David
  • 208,112
  • 36
  • 198
  • 279
1

Instead I need a way to retrieve the data-taskId value from the complete button and push it through to the complete button's onClick function, I'm not sure how to do this and also adhere with good practice.

Whether it's "good practice" is a bit opinion-based. You'll need to be sure that if the user goes in with devtools and modifies the attribute to a task they shouldn't be able to complete, the server will refuse to complete it. (But that's just a variation on "never trust anything the client sends you." :-) )

To use that task ID, just get it from the button:

$(".status-button").on("click", function (event) {
   var status = $(".case-status").val();
   var taskId = $(this).attr("data-taskId"); // <==================
});

See this answer for why I used attr there, not data. You may prefer to use attr, or data, depending on whether you want to use jQuery's data cache. For something simple like this, it seems like overkill.


This line is a bit suspect:

var status = $(".case-status").val();

Provided you really do only want the value of the first matching element regardless of which complete button was pressed, that's fine. If you need to find one .case-status out of many (the one related to the task being completed), we'd need to see your HTML to describe how to do that, but usually it's possible with closest and find.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875