3

I feel like my need is pretty basic, but I'm having trouble finding an example.

I don't use jQuery much but I need a function that loops through every row in a given table and then loops through each input in that row to then re-index each id and name attribute in sequential order. The server side application needs sequentially numbered inputs in order to build the list of objects correctly. I have separate functions that remove and add rows so there is potential for a user to remove rows in the middle creating a gap.

To start I've got this but I'm unsure how to do a loop inside a loop with jQuery and simply commented that section.

Edit: I've provided a snippet of the HTML as well for a little more context. For the server-side application to collect the objects the name attribute just needs to be enumerated like AccountCodes[0].Id and then AccountCodes[1].Id instead of [0],[6] for example.

        

function LoopAccountCodeRows() {
  var accountCodeIndex = 0;
  $('table#AccountCodeTable tbody tr').each(function () {
      //loop through input logic here
      $(this).attr("id", $(this).attr("id").replace(/\d+/, accountCodeIndex));
      $(this).attr("name", $(this).attr("name").replace(/\d+/, accountCodeIndex));
      //end input loop

      accountCodeIndex++;
  });   
}
<table id="AccountCodeTable">
    <thead><tr><th></th><th>Account Codes</th><th>Budget Estimate Percent</th></tr></thead>
    <tbody>
      <tr>
        <td style="padding:.5rem;">
        </td>
        <td style="padding:.5rem;">
            <input id="AccountCodes_0__Id" name="AccountCodes[0].Id" type="hidden" value="135" />
            <input id="AccountCodes_0__Action" name="AccountCodes[0].Action" type="hidden" value="Add" />
            <input id="AccountCodes_0__AccountCode" name="AccountCodes[0].AccountCode" type="hidden" value="20-10-09-086" />
            20-10-09-087
        </td>
        <td>
            <input type="number" class="form-control percent"  id="AccountCodes_0__PercentTotal" name="AccountCodes[0].PercentTotal" value="0.10" />
            <span class="text-danger field-validation-valid" data-valmsg-for="AccountCodes[0].PercentTotal" data-valmsg-replace="true"></span>
        </td>
      </tr>
      <tr>
        <td style="padding:.5rem;" >
        </td>
        <td style="padding:.5rem;">
            <input id="AccountCodes_6__Id" name="AccountCodes[6].Id" type="hidden" value="135" />
            <input id="AccountCodes_6__Action" name="AccountCodes[6].Action" type="hidden" value="Add" />
            <input id="AccountCodes_6__AccountCode" name="AccountCodes[6].AccountCode" type="hidden" value="20-10-09-087" />
            20-10-09-087
        </td>
        <td>
            <input type="number" class="form-control percent"  id="AccountCodes_6__PercentTotal" name="AccountCodes[6].PercentTotal" value="0.10" />
            <span class="text-danger field-validation-valid" data-valmsg-for="AccountCodes[6].PercentTotal" data-valmsg-replace="true"></span>
        </td>
      </tr>
    </tbody>
    </table>
3
  • Why not use a JS for() loop on the element you are looking to loop over? Commented Nov 28, 2020 at 17:43
  • "The server side application needs sequentially numbered inputs in order to build the list of objects correctly." - That sounds like a bug in the server application. It would make sense to fix the server end. (Besides, the element IDs are not transmitted to the server anyway, fixing them is pretty much useless.) Commented Nov 28, 2020 at 18:36
  • An Enumerated list of objects needs a sequential index to be registered server side. And yes altering the element IDs is unnecessary, I just like matching the ID/name in case of any other client side logic in the future. Commented Nov 28, 2020 at 19:34

2 Answers 2

4

How is "looping all <tr>s and then all <inputs> inside them" any different from "looping all <input>s in the <table>"?

$('#AccountCodeTable tbody input').attr('name', function (i) {
    return this.name.replace(/\d+/, i);
});

Many jQuery functions accept a callback that receives the index as the first parameter and use the function return value. .attr() is not an exception.

The element IDs are not transmitted to the server anyway, so I'm not changing them here.

A variant that uses the index of the <tr> instead of the index of each <input> works exactly the same, it starts the way your attempt started:

$('#AccountCodeTable tbody tr').each(function (i) {
    $(this).find('input').attr('name', function () {
        return this.name.replace(/\d+/, i);
    });
});
Sign up to request clarification or add additional context in comments.

4 Comments

The multiple inputs for each row need the same index because on server side they are properties of same object. This would increase the index after each input if I understand correctly.
@Jalashuk How about you show the HTML in your question and explain what indexes you need where, exactly?
@Jalashuk See modified answer.
Thank you, exactly what I was hoping for a very simple solution.
0

I still have not quite understopod your exact requirements but when you look at the following snippet you will notice that a single loop over all input elements is quite enough to generate all the identities and names you might require:

function renumber() {
  $('#AccountCodeTable input').each(function (i,el) {
     el.name=el.name.replace(/\d+_?\d*/,
       $(el).parent().parent().index()+'_'+$(el).parent().index());
     el.id=el.id.replace(/\d+/,i);
     // comment out the following line for production version:
     el.value="id:"+el.id+", name:"+el.name;
  })
}
renumber()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="AccountCodeTable">
<tbody>
<tr>
 <td><input type="text" id="i3" name="n3"></td>
 <td><input type="text" id="i4" name="n33"></td>
 <td><input type="text" id="i5" name="n333"></td>
 <td><input type="text" id="i6" name="n3333"></td>
</tr><tr>
 <td><input type="text" id="i8" name="n13"></td>
 <td><input type="text" id="i9" name="n113"></td>
 <td><input type="text" id="i10" name="n1113"></td>
 <td><input type="text" id="i11" name="n11113"></td>
</tr><tr>
 <td><input type="text" id="i12" name="n32"></td>
 <td><input type="text" id="i13" name="n322"></td>
 <td><input type="text" id="i14" name="n32_22"></td>
 <td><input type="text" id="i15" name="n3_2222"></td>
</tr><tr>
 <td><input type="text" id="i16" name="n34"></td>
 <td><input type="text" id="i17" name="n344"></td>
 <td><input type="text" id="i18" name="n3444"></td>
 <td><input type="text" id="i19" name="n34444"></td>
</tr>
</tbody></table>

In my renumber() function I renumber the ids sequentially and the names by giving them a composite name consisting of row and column number. You can leave one of them out or even combine them in a different way. However you like it

2 Comments

I think what you did here will work. You may have just gone further with replace than I need. I will re-work into my app and see it works. Thanks.
Thank you. This does work, it just wasn't quite as simple as Tomalak's solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.