views:

383

answers:

6

Hi there. If I have a page with a form (imagine a simple one with just TextBoxes and a submit button) and I want to allow the user to dinamiccally add more TextBoxes to the form via javascript, what is the best way to handle the request server side?

Example: I have a page rendered like the following :

<input type = "text" id = "control1" name = "control1" />
<input type = "text" id = "control2" name = "control2" />
<input type = "text" id = "control3" name = "control3" />
<input type = "submit" />

The user trigger some Javascript and the page turns out like:

<input type = "text" id = "control1" name = "control1" />
<input type = "text" id = "control2" name = "control2" />
<input type = "text" id = "control3" name = "control3" />
<input type = "text" id = "control4" name = "control4" />
<input type = "text" id = "control5" name = "control5" />
<input type = "submit" />

What is the best way to handle this kind of situation, or, more generally, working with dinamically generated input both client and server side (eg, how to generate them server side starting from, say, some data taken from a database)?

Thanks

A: 

On the server side look into Request.Form["controlN"] where you will find your old and new fields.

On the server side you can add controls dynamically like:

foreach (Type object in MyDBCollection)
{
   Controls.Add (new TextBox ());
}
User
+1  A: 

On client side, make a JS function for creating the inputs, for example:

var numCtrl = 1; // depends on how many you have rendered on server side
var addCtrl = function() {
    var in = document.createElement('input');
    in.name = "control" + ++i;
    in.type = "text";
    in.id = "control" + i;
    document.getElementById("yourcontainer").appendChild(in);
}

..on the server side just lookup your HTTP params collection, iterate through it, and select only those matching /control\d*/

skrat
Could you please tel me how i can access the HTTP params collection?
bahith
A: 

In webforms you won't have a lot of choices if you expect the values to postback and be able to access them in typical fashion. What I would suggest is that you use an Ajax UpdatePanel to allow the controls to be registered at the appropriate point of the page lifecycle (before onLoad), this will also make a difference on whether or not you need the boxes to persist across postbacks. The JS methods involved in the other 2 answers will not persist the textboxes through a postback.

MVC gives you more leeway, since there isn't that crazy page lifecycle, control registration, viewstate, etc to get in your way.

So the big question is, which model/framework for ASP.Net are you using?


Since you are indeed using webforms, I really strongly suggest you go with updatepanels if they'll work for you. it will permit you to add controls in such a way that wont get in the way of eventvalidation, etc.

Chad Ruppert
Hi, thanks for your answer. I'm using webforms, by the way. I'm a bit tempted by MVC, but what I like in ASP.NET's webforms is the rapid developement.If I wanted to slow development time down and approach the MVC pattern, I think I'd go for something more mature like Django.
pistacchio
fwiw, I actuallt find MVC considerably more rapid than webforms, but then I despise asp.net webforms :)
annakata
The problem with webforms is that once you get further and further outside of 'the box' the more and more crufty it feels. If you want to take advantage of all the ajaxy goodness, webforms often gets in the way with its mangling of html element ID's and such.
Chad Ruppert
Not that I disagree with you, but I find that to be just one of *many* major problems :)
annakata
Oh, there are a buttload of issues with webforms. However, from what I've seen, to the average dev who is just trying to make something work, and doesn't care to understand all of the issues, this is probably the first of many annoyances.
Chad Ruppert
+1  A: 

If you want to be able to access them in the code behind using the FindControl method, the AJAX UpdatePanel is probably your best bet. Just remember that every time you update the UpdatePanel, your going through the entire page life cycle but only getting the pieces that render in the update panel back from the server, so be weary of the overhead.

If you create them dynamically with Javascript you will not be able to use FindControl to get access to them in the code behind because they won't be re-created during the page event life cycle. Also, be careful because if you're creating a lot of them at the same time with some kind of loop it can slow things down, especially in Internet Explorer.

You may also consider using AJAX and WebServices with WebMethods for submitting the data instead of a post-back if you're creating the controls dynamically with Javascript.

Justin
A: 

I've begun using jquery in a lot of my webforms applications and have found the combination of dynamic controls and using JSON to communicate with the page's WebMethods give me much more control over how the page is presented and eliminate needless postbacks.

When I want to trigger a postback, I use javascript to populate server controls on the page that are hidden by jquery and then click a server control button. This allows the page to degrade gracefully if the user cannot use javascript.

KClough
+1  A: 

I have done similiar things to this numerous times. My preferred approach is usually to use a Repeater and a Button (labelled Add) inside an UpdatePanel.

For the Button_OnClick event in your code behind do something similiar to this;

 Loop through the Items collection of the Repeater
 Use item.FindControl("txtUserInput") to get the TextBox for that item
 Save the text of each input to List<string> 
 Add an empty string to the the list
 Databind the repeater to this new list

Here's some example code;

<asp:Repeater runat="server" ID="rptAttendees">
 <ItemTemplate>
  <asp:TextBox runat="server" ID="txtAttendeeEmail" Text='<%# Container.DataItem %>'></asp:TextBox>
 </ItemTemplate> 
</asp:Repeater>



protected void btnAddAttendee_Click(object sender, EventArgs e)
{
    var attendees = new List<string>();

    foreach (RepeaterItem item in rptAttendees.Items)
    {
        TextBox txtAttendeeEmail = (TextBox)item.FindControl("txtAttendeeEmail");
        attendees.Add(txtAttendeeEmail.Text);
    }

    SaveAttendees();
    attendees.Add("");
    rptAttendees.DataSource = attendees;
    rptAttendees.DataBind();
}
Kirschstein