Nick Amor
Nick Amor

Reputation: 31

How to Get All HtmlInputText Controls Within a Table Row?

I'm trying to create a web page to create small playlists. Once data has been entered into the fields, it needs to be saved to an XML file. Currently the table looks like this:

<%-- song list table --%>
<table runat="server" id="table" class="table">

<%-- info row --%>
<thead>
 <tr>    
  <td>Song Title</td>
  <td>Song Artist</td>
  <td>Song Album</td>
  <td><%-- column for delete button --%></td>
 </tr>
</thead>

<%-- input rows --%>
<tbody>
 <tr>
  <td><input runat="server" placeholder="Title" type="text" /></td>
  <td><input runat="server" placeholder="Artist" type="text" /></td>
  <td><input runat="server" placeholder="Album" type="text" /></td>

  <td>
   <a href="#">
    <img src="Images/Delete.png" onmouseover="this.src='Images/Delete-Hover.png'" onmouseout="this.src='Images/Delete.png'" alt="Delete" />
   </a>
  </td>
 </tr>
</tbody>

</table>

New rows will be added dynamically with jQuery. When the user clicks save, I need to write the table data into their specific XML file. Currently my backend code looks like this:

//for each row
foreach (HtmlTableRow row in table.Rows)
{
 //create row info
 textWriter.WriteStartElement("Row");

 //for each cell
 foreach (HtmlTableCell element in row.Cells)
 {
  //get inputs

  //write current input to xml
 }

 //close row
 textWriter.WriteEndElement();
}

My question is where I go from there with my code to be able to get the values of each input and write them to the XML.

Upvotes: 2

Views: 1008

Answers (2)

Troy Alford
Troy Alford

Reputation: 27236

My suggestion would be to re-think how you're gathering the data. I assume that you're going to have this information do an HTTP POST to your server using $.ajax() or something similar - and on the server-side, you're wanting to get all of the instances of the Title, Artist and Album fields, grouped by row.

Instead of posting back the table, which is a set of UI elements that display your data, but do not represent it, consider posting back to the server and having the server expect an IEnumerable of Song objects, which would look something like this:

public class Song {
    public String Album { get; set; }
    public String Artist { get; set; }
    public String Title { get; set; }
}

Now, when you bind the form itself, you can bind something like:

<table>
 <thead>
  <tr>    
   <td>Song Title</td>
   <td>Song Artist</td>
   <td>Song Album</td>
   <td><%-- column for delete button --%></td>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td><input placeholder="Title" type="text" name="Songs[0].Title" /></td>
   <td><input placeholder="Title" type="text" name="Songs[0].Artist" /></td>
   <td><input placeholder="Title" type="text" name="Songs[0].Album" /></td>
  </tr>
 </tbody>
</table>

The [0] notation indicates that this element is part of an IEnumerable called Songs, and is at index 0. When your jQuery script then goes and adds new rows, you simply increment the indexes. So - a new row would be something like:

 <tr>
  <td><input placeholder="Title" type="text" name="Songs[1].Title" /></td>
  <td><input placeholder="Title" type="text" name="Songs[1].Artist" /></td>
  <td><input placeholder="Title" type="text" name="Songs[1].Album" /></td>
 </tr>

The only trick to this is to ensure that you never have gaps in your indexes. I.E. - if you have 5 rows, and you delete the third, you need to re-index rows 4 and 5 (by decrementing the [#] values).

Note: All of the above assumes you are using server-side binding.

If you are already using jQuery, you might also find it simpler to simply parse your table's input elements with jQuery and post things as an object that you have direct control over. This prevents you from having to do any indexing at all. An example would be something like:

$('#submit-button').on('click', function (ev) {
    var songs = [];
    $('#table > tbody > tr').each(function (index, element) {
        var $tr = $(element);

        var album = $tr.find('input[placeholder=Album]').val();
        var artist = $tr.find('input[placeholder=Artist]').val();
        var title = $tr.find('input[placeholder=title]').val();

        songs.push({ Album: album, Artist: artist, Title: title });
    });

    $.ajax({
        url: '/my/post/url',
        type: 'POST',
        data: songs
    });
});

On the server-side, you will now receive an HTTP POST to /my/post/url which has a payload containing the song data in the table - without having to worry about funky data-binding syntax or indexing.

Hope this helps.

Upvotes: 1

Brian Mains
Brian Mains

Reputation: 50728

You need to give the element's an ID so you can refer to them by. Also, any dynamically added rows will not be able to be accessed this way; that is because they do not exist in the control tree as a server control, but are a pure client control. You would have to access these using Request.Form collection. You'd have to add them dynamically to the control tree if you want them to persist across postbacks too.

If you are using JQuery, it would be more efficient and easier to grab all the values on the client and send the values to a web service or something like that.

Upvotes: 1

Related Questions