views:

69

answers:

2

i have an html table inside a form in an asp.net mvc view. I am using the tablesorter jquery plugin as well.

Here is the table code (simplified for the example)

 <table id=managersTable>
 <thead>
     <tr>
           <th>Manager</th><th>Remove</th>
     </tr>
 </thead>
 <tbody>
 <tr>
      <td>Manager 1<input type='hidden' name='updater.managers[0].Id' value=2313 /></td>
 <tr>
      <td>Manager 2<input type='hidden' name='updater.managers[1].Id' value=3233/></td>
      <td><input type='button' class=removeButtonManager value='Remove' name='remove' /></td>
 </tr>
 </tbody>

so as you can see, there is a column with text and a second column with a button. I have it hooked up so when you click on the button it removed the row from the html table using this code:

    $(document).ready(function() {
        $(".removeButtonManager").live("click", function(event) {
            var row = $(this).closest("tr").get(0);
            $(this).closest("tr").remove();
            $("#managersTable").trigger("update");
            $("#managersTable").trigger("appendCache");
        });
     });

Everything works perfectly fine except one issue. When i click on a "remove" button it removed the row but the issue then is that the index for

name='updater.managers[0].Id'

is now off and it looks like in the latest version of asp.net mvc binding if you dont have your elements indexed property (0,1,2,etc . .) it doesn't bind.

so if i never delete a row it works perfectly as its 0,1,2 originally but if i delete the first row then i only have list (1,2 . .) and asp.net mvc wont bind this object.

so i am trying to figure out how i can reset the [] index in each of the elements after i remove a row so no matter if a remove any row, it always gives me a continuous list starting from 0.

+1  A: 

I think you'll have to loop through all the elements and fix the ids. Something like this should work

$(document).ready(function() {
    $(".removeButtonManager").live("click", function(event) {
        var row = $(this).closest("tr").get(0);
        $(this).closest("tr").remove();
        $("#managersTable").trigger("update");
        $("#managersTable").trigger("appendCache");
        $("#managersTable").find("input[type=hidden]").each(function(i){
           //this is the current input we're looping through
           //i is the index
           $(this).attr('name', 'updater.managers['+i+'].Id');
        });
    });
 });

Take a look at the docs for each (http://docs.jquery.com/Utilities/jQuery.each#objectcallback) if it doesn't work right away, I could have mixed something up. Hope that helps

John Duff
so this partially worked (upvoted for the good idea). one issue is that in the case above, where i have 2 rows to start (elements 0,1) and i delete the first row (after the code above i should have one element) i get the data of the second row now in element 0 (perfect) but i also get a second element (1) that returns an object with all of the properties set. any ideas ??
ooo
I'm not really sure what you mean. $("#managersTable").find("input[type=hidden]") returns an array and there are two elements in it? Maybe the selector needs to be more specific so that it only targets the table. I'm not really sure what you mean by 'all the properties are set' on this second object.
John Duff
ooo
so to add, it seems like your above code is resetting the element name='updater.managers[1].Id' toname='updater.managers[0].Id'which is great but there now seems to be an empty:name='updater.managers[1].Id'laying around
ooo
It sounds like the selector I gave you is a little too general, try "td input[type=hidden]" to see if that is specific enough. Also see if you can put a breakpoint into each function and see how many times it is going through that loop, if there is a second element maybe you'll be able to come up with a selector that doesn't include that one .not('.someclass') after the find call. Let me know what you find.
John Duff
hmm . .same issue . . but something new. i just tested it where i started with 4 rows and deleted 2 of them. when i sent the 2 to the controller, it only had two elements so it worked in this case. So somehow going from 2 rows to 1 row seems to have this issue but going from 4 to 2 doesn't . . hmm . . .
ooo
A: 

It is also possible to add a hidden input field like

<input type='hidden' name='updater.managers.Index' value="0" />

for each of the list, which is posted back to model binder as a list of indexes in the form of [0,2,3...]. And the collection model binder will iterate through those indexes instead of "trying" continuous index.

Value of .Index field can be either numbers or strings.

For more details, refer to the last part of this blog post: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

Bill Yang