views:

152

answers:

2

...meaning pattern in its general English usage, not specific to OO design patterns. Given a table like the following (using <% %> as generic server-side script tags):

<form action="someUri" method="post">
<table>
    <thead>
        <tr>
            <td>Widget ID</td>
            <td>Description</td>
            <td>Price</td>
        </tr>
    </thead>
    <tbody>
    <% foreach widget in widgets %>
        <tr>
            <td>
                <!-- input ids need to be mangled
                        to preserve uniqueness -->
                <input type="hidden" id="[Some_Mangled_Input_Id]" 
                    value="<%= widget.Id %>" />
                <%= widget.Id %>
            </td>
            <td>
                <!-- prefill if exists for widget -->
                <input type="text" id="[Some_Mangled_Input_Id]"
                    value="<%= widget.Description %>" />
            </td>
            <td>
                <!-- prefill if exists for widget -->
                <input type="text" id="[Some_Mangled_Input_Id]"
                    value="<%= widget.Price %>" />
            </td>
        </tr>
    <% end foreach %>
    </tbody>
</table>

<input type="submit" value="Save Changes" />
</form>

And on the server at post:

    var widgetIdKeys = all keys in forms collection matching
        pattern of mangled input Id for Widget.Id hidden input

    foreach widgetIdKey in widgetIdKeys

        find matching mangled input Id for Widget.Description text input

        find matching mangled input Id for Widget.Price text input

        if input changed per comparison to some original

            persist Description and Price input for current widget Id

        end if

    end foreach

This problem has no doubt been solved for a long time but this is the only approach I can think of and it seems hacky. So my question is: is there a better pattern and if so what does it look like? If this is the only or preferred way to do this, are there right and wrong ways to handle the input Id mangling and parsing? What about the comparison to identify which inputs have changed? I can think of ways to solve this on a per row or per cell level, and maybe those ways exist because there is no good way to solve it on a per table level, but I can also think of downsides to those ways.

Or am I missing the appropiate paradigm altogether? Thanks for any insights.

+2  A: 

You might want to use name instead of id for your inputs.

http://www.mail-archive.com/[email protected]/msg27766.html

Name and ID serve two different purposes. ID is used to identify the element's node in the document. Name is used to identify the element's value in the form submission posted back to the server.


You could simplify things by using an arrays for your input names:

<% for (i=0; i<n; i++) { %>
<input type="hidden" name="id[i]" />
<input type="text" name="description[i]" />
<% } %>

Then on the backend the inputs would all be nicely arranged in arrays (at least in PHP).

More here.

willoller
Good to know. I was unaware of the possibility of naming inputs as array elements. I'm using ASP.Net MVC currently but even if the inputs aren't automatically converted to arrays it's a new perspective. Also, can you tell me more about the advantage of using name instead of id for inputs?
I Have the Hat
Well for one if you tried this technique with ids instead of names it wouldn't work; it's valid to repeat names in a form if you want (at your peril!), but ids must be unique for a whole document.
willoller
(I say peril because of browser issues that can come up using the same name for mulitple things, esp. submit buttons.)
willoller
Thanks. I was aware of the validity requirement for unique Ids. I just wondered if there was something else about the name attribute that I wasn't aware of.
I Have the Hat
Just that you can skip the whole "mangled id" step if you make good use of names, which should save you some time and make your page easier to maintain - and isn't that the point of patterns? :)
willoller
Ah yes, good info about names and ids. I knew ids had to be unique and names did not but I had long been misled to believe that ids were required and names were not, and that id was the attribute explicitly translated into a key in the request, which according to the link is not the case. It acutally makes more sense that id is for the DOM, name is for the form submission. That gives one much more flexibility to work with.
I Have the Hat
It turns out that ASP.Net MVC has some good facilities for model binding forms to typed collections... providing a big chunk of the solution http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx.
I Have the Hat
A: 

For completeness (not trying to get my own bounty if that's even possible) here is how I ended up addressing the problem—not much different than the original approach, just more sane in large part due to willollers answer that put me on the right track.

Adding a row counter to the table above I modified the original input id/name pattern such that the incoming form submissions looked like this:

<input name="widgets[0].Id" />
<input name="widgets[0].Description" />
<input name="widgets[0].Price" />
<input name="widgets[1].Id" />
<input name="widgets[1].Description" />
<input name="widgets[1].Price" />
<input name="widgets[2].Id" />
<input name="widgets[2].Description" />
<input name="widgets[2].Price" />

And so on.

This is exactly what is prescribed by ASP.Net MVC as shown by Scott Hanselman here. ASP.Net MVC's default model binder will take it from there and automatically convert the submission to a strongly typed collection named widgets, but to keep to the point of the question as language/framework agnostic, I think the take-away is to use an input naming convention that can easily be parsed into a collection and focus on abstracting that step. From willoller's answer that task is handled nicely by PHP, and I would guess there are similar facilities in other platforms as well.

I Have the Hat
Hi,I think it is better you edit one record at once instead many at once. In my answer, when a user click Edit user, a dialog will be pop up. If you choose edit many records at once, failures can occurs whether some index is lost or a new index is added to your list or even one index overlaps another. Think about it.
Arthur Ronald F D Garcia
Yup, persisting changes to a collection at once is hard and error prone. Persisting a record at once is (relatively) easy and arguably preferable, but that's not the problem the question is attempting to solve.
I Have the Hat
Thanks for your comment. If i wish managing many records at once, i use an Object to Relational Mapping Framework like NHibernate (.NET), nothing else. It takes care insert a new record or update an existing record. It checks record changes and saves or updates it. It works fine.
Arthur Ronald F D Garcia