How to Capture the Row Index to Use in a JS Function

I am excited to share with you a deep dive into capturing dynamic row indexes for JS functions in a project that creates multiple form elements. I’ll walk you through my process of creating a dynamic form using JSP and Spring tags, how I leveraged a Java loop to generate individual form elements, and then how I modified my JavaScript to interact with each input field without hardcoding indexes.

Project Overview

In my project, I generate multiple form elements based on the length of an array called allFilmsArray. Each film detail is rendered inside a fieldset with a unique ID that incorporates the current index. The basic structure in the JSP looks like this:

<form:form modelAttribute="formTT1" onsubmit="javascript:return submitForm();"> 
<div id="leftcontent">
<div id="centercontent">
<div id="FieldsetsContainer">
<fieldset id="filmCreditDetails">
<legend>
<span class="SectionHeading" id="filmCreditSectionHeading">
<spring:message code="24201"/>
</span>
</legend>
<%
Object[] allFilmsArray = formTT1.getfilmCredit().getfilmList().toArray();
int numOfDetails = allFilmsArray.length - 1;
for (int i = 0; i <= numOfDetails; i++) {
%>
<fieldset id="FilmDetails<% out.println(i); %>">
<legend>
<span class="Level2FieldSetHeading">
<spring:message code="24202" arguments="<%= new Object[] { i+1 } %>"/>
</span>
</legend>

<div class="Ct1FormField">
<label for='<%= "filmCredit.filmList[" + i + "].filmCertNumber" %>'>
<spring:message code="24203"/>
</label>
<span class="notCurrency">
<ss:input path='<%= "filmCredit.filmList[" + i + "].filmCertNumber" %>' maxlength="20" forcedisable="<%= !bAmend %>"/>
</span>
</div>

<div class="Ct1FormField">
<label for='<%= "filmCredit.filmList[" + i + "].qExpense" %>'>
<spring:message code="fct29"/>
</label>
<span onkeyup="checkInput(this);" class="currency">
<ss:input path='<%= "filmCredit.filmList[" + i + "].qExpense" %>' forcedisable="<%= !bAmend %>" />
</span>
</div>
</fieldset>
<% } %>
</fieldset>
</div>
</div>
</div>
</form:form>

In the code above, I loop through each film record to create individual fieldsets. Notice that the IDs for the input fields are constructed dynamically (for example, 'filmCredit.filmList[0].qExpense', 'filmCredit.filmList[1].qExpense', etc.) so each form element is uniquely identified.

The Initial Problem

Initially, I had a JavaScript function that retrieved the value of the qExpense field only for the first form element. It was hardcoded like this:

function checkInput(val) {
var myTextBox = document.getElementById('filmCredit.filmList0.qExpense');
var value = myTextBox.value;
if (!value || isNaN(value) || parseInt(value, 10) < 20000000) {
myTextBox.style.color = 'green';
document.getElementById('ifYes').style.display = 'block';
} else {
myTextBox.style.color = 'red';
document.getElementById('ifYes').style.display = 'none';
}
}

This solution worked for the first field, but as soon as a user interacted with subsequent forms, the function wouldn’t retrieve their values. I needed a way to capture the dynamic row index to ensure that the correct qExpense value was being validated.

The Dynamic Approach

Leveraging the “this” Keyword

I realized that since each input field already calls checkInput(this) on keyup, the element that triggers the function is passed as an argument. Instead of hardcoding the ID inside the function, I can use the passed element directly. This small change makes the function much more dynamic:

function checkInput(inputElement) {
var value = inputElement.value;
if (!value || isNaN(value) || parseInt(value, 10) < 20000000) {
inputElement.style.color = 'green';
document.getElementById('ifYes').style.display = 'block';
} else {
inputElement.style.color = 'red';
document.getElementById('ifYes').style.display = 'none';
}
}

By doing this, every time the user types in any of the qExpense fields, the function directly works on the element that fired the event. No more hardcoding or manual index extraction!

Ensuring Unique Element Identification

In some cases, you might need to know the index (for example, if you want to update other elements related to the same row). You have two common approaches:

  • Using the Element’s ID:
    Since each field’s ID contains the index (e.g., filmCredit.filmList[0].qExpense), you can parse the id string inside your function to extract the index if needed.
function checkInput(inputElement) {
// Example: Extract the index from the element's id
var id = inputElement.id; // e.g., "filmCredit.filmList0.qExpense"
var indexMatch = id.match(/filmCredit\.filmList\[(\d+)\]\.qExpense/);
if (indexMatch) {
var index = indexMatch[1];
console.log("Current index is: " + index);
}
// Proceed with validation using inputElement directly
var value = inputElement.value;
if (!value || isNaN(value) || parseInt(value, 10) < 20000000) {
inputElement.style.color = 'green';
document.getElementById('ifYes').style.display = 'block';
} else {
inputElement.style.color = 'red';
document.getElementById('ifYes').style.display = 'none';
}
}
  • Passing the Index as an Argument:
    Alternatively, you could pass the index directly from the JSP when calling the function. For example:
<span onkeyup="checkInput(this, <%= i %>);" class="currency">

And then update the JavaScript function accordingly:

function checkInput(inputElement, index) {
console.log("Processing input for row: " + index);
var value = inputElement.value;
if (!value || isNaN(value) || parseInt(value, 10) < 20000000) {
inputElement.style.color = 'green';
document.getElementById('ifYes').style.display = 'block';
} else {
inputElement.style.color = 'red';
document.getElementById('ifYes').style.display = 'none';
}
}

Either approach ensures that your JavaScript function dynamically knows which row is interacting with it. I personally lean toward the first method using this because it makes the code cleaner and leverages native JavaScript functionality.

Final Thoughts

I am a firm believer in writing modular and dynamic code. By removing hardcoded values and using event parameters, I not only simplified my JavaScript function but also made the entire form interaction more robust and maintainable. Whether you choose to extract the index from the element’s ID or pass it explicitly from the server-side code, the goal is to make your code adapt to the number of dynamic elements on the page.

Related blog posts