0

Here's my situation:

I'm writing an ASP.net MVC 1 website and I have a create/edit form that uses the default model binding to parse the form into a strongly typed complex object.

The object I'm posting has a child collection of another complex type and the way I format my id's for the model binder is as follows:

<div class="childContainer" >
   <!-- There's one of these for each property for each child collection item -->
   <%= Html.TextBox("ChildCollectionName[0].ChildPropertyName", /* blah blah */ ) %>
   <%= Html.TextBox("ChildCollectionName[0].OtherChildPropertyName", /* blah blah */ ) %>
   <!-- ... -->
</div>

This gets rendered as

<div class="childContainer" >
    <input id="ChildCollectionName[0]_ChildPropertyName" ... />
    <input id="ChildCollectionName[0]_OtherChildPropertyName" ... />
...
</div>
<div class="childContainer" >
    <input id="ChildCollectionName[1]_ChildPropertyName" ... />
    <input id="ChildCollectionName[1]_OtherChildPropertyName" ... />
...
</div>

For each entry in the chlid collection.

This collection is dynamically created in the form using jQuery, so entries can be added, removed etc. and whenever there's an operation on the collection I need to update the indexes so that it's bound correctly on the server side.

What's the best way to replace all the html input id's when I'm updating the index within the child e.g.

replace all [*] --> [N] where N is the correct index.

using jQuery / JavaScript ?

I have something coded now, but its buggy and I think there is a simpler solution.

Also, if you have an easier way to identify the child collection I'll take any advice on that as well.

Thanx!

TJB
  • 13,367
  • 4
  • 34
  • 46
  • 1
    Normally the css class name does not have a leading dot. I'm not even sure that's legal, valid syntax. Also, you haven't explained clearly enough what you want to do. You're talking about ids ("the way I format my id's is as follows.."). But I don't see any ids. Are you referring to ids on the elements in the HTML document? I don't see any. maybe you can restate the question in simpler, clearer terms. – Cheeso Mar 19 '10 at 21:27
  • You ought to provide the full HTML output generated by the call to Html.TextBox, assuming that holds the DOM ID that you're looking to capture, (and also assuming this code is iterated upon). – Matt Huggins Mar 19 '10 at 21:35
  • @Chesso the css name was a typo in my case (not copy-pasted) I added a simplified version of the html output, I can't post the actual code (proprietary) but this should give a better idea of what I'm trying to do... – TJB Mar 19 '10 at 21:44

2 Answers2

2

I've done a similar thing where I was using a dynamic list of Model objects in my View. I used a table structure for my form but I'm sure you could apply similar logic.

I used buttons that would add/remove table rows. You have to maintain numerical order when submitting your form so id's should be 0,1,2,3 and cant be 0,2,3,4 etc. My design was simpler where you could only add an item to the bottom of the list and only remove the last item in the list. Therefore I could maintain the id's in order.

You might find some of the code useful when manipulating your dynamic form.

$('.add').live('click', function()
{
    var addRowId = $('#myTable tr').length;
    var internalId = addRowId - 1; //subtract -1 for header row

    //clone the last row
    var row = $('#ft tr:last').clone(false);

    //modify the input id and name values
    row.find(':input')
        .attr('id', function() { return 
            $(this).attr('id').replace(/\[[\d+]\]/g, '[' + internalId + ']');
        })
        .attr('name', function() { return 
            $(this).attr('name').replace(/\[[\d+]\]/g, '[' + internalId + ']');
        });

    //add the new row
    $('#ft tr:last').after(row);

    return false;
});

Note: I found a change when upgrading to MVC 2 with generation of id's has changed...

ASP.NET-MVC2 Preview 1: Are There Any Breaking Changes?

Community
  • 1
  • 1
David
  • 15,150
  • 15
  • 61
  • 83
  • Thanks for the heads up about the v2 changes, your solution includes some selectors I was not aware of, they will be helpful. I'm actually also using a table structure but omitted that for simplicity in the question. The other difference is that I allow removal of any item, but still this is very applicable and helpful. Any good techniques for skipping the header row of the table when iterating through it? Right now I'm just using something like if( $(this).find("th").length == 0 )... where this is a "tr", don't know if there's a better way... Thanks! – TJB Mar 20 '10 at 20:06
  • You could distinguish this by using < thead > and < tbody > and in your javascript use $('#mytable tbody tr').length should work. – David Mar 20 '10 at 20:17
0

Instead of manipulating the DOM elements each time the collection changes, you can keep an array of your elements in a JavaScript variable and directly work with that array when you need to add/remove an element. And then re-render the input elements using the array.

Çağdaş Tekin
  • 16,592
  • 4
  • 49
  • 58