views:

99

answers:

4

I have an ASP.Net web site and on one of the pages I'm using a repeater to render several iterations of a UserControl, that UserControl contains a second UserContol that has two text boxes that my User must enter information into. I want to be able to have my user push a button and add another instance of the second UserControl (with the two textboxes) to my original UserControl, so that the user has 4 textboxes displayed on the screen for the first UserControl. The problem I am seeing if I try to add the second UserControl to a given iteration of the first, is that the page postback causes any other of these second user controls to be deleted from the page.

Does anyone know of a way to do this using JQuery? I've had three posts that describe how to solve this problem using server side dynamic controls, and/or AJAX, but we've decided to focus on a JQuery solution because this server side mechanism is too costly in terms of resources for us.

I've been working on the suggestion by Zincorp below, and now have the JQuery working to clone a textbox, but having trouble using the server side Request.Form collection to iterate over the controls. Can anyone give adivce on how to iterate over the Request.Form collection?

OK, I think the problem with iterating over the controls using the Request.Form.AllKeys collection turned out to be that I was using an HTML Textbox, rather than an ASP TextBox Control. Apparently the Request.Forms.AllKeys collection only contains ASP controls, not HTML controls.

The problem I am seeing now is that when I clone the control in JQuery, and then submit my page with the submit button, the 2 controls have the same ID, and so are combined (I think) by http into one ASP TextBox Controls containing both values, with a comma delimiter (e.g.- 40,20). Anyone know how to get a new ID assigned to the cloned ASP TextBox?

Here is the updated markup in a sample ASP.Net web appliction:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs"   Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;

<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
        <asp:Label runat="server" ID="ProjectDisplay" Text="Project" />
        <asp:TextBox ID="ProjectValue" runat="server" ></asp:TextBox>
        <div id="mydiv" ></div>
        <br />
        <br />
        <br />

    <input id="AddProject" type="button" value="Add Project" />    
        <br />
        <br />


    <asp:Button ID="Submit" runat="server" Text="Submit" onclick="Submit_Click" />

</div>
</form>
</body>
</html>
<script language="jquery" src="js/jquery-1.3.2.js" type="text/javascript"></script>
<script type="text/javascript" >

$(document).ready(function() {

  $("#AddProject").click(function() {

      var x = $("#ProjectValue").clone();

      x.appendTo("#mydiv");     
  });
});
</script>

And here is the updated server side code where I'm trying to iterated over items in the Request.Form collection to get information from it:

public partial class _Default : System.Web.UI.Page 
{
protected void Submit_Click(object sender, EventArgs e)
{
    foreach (string s in Request.Form.Keys)
    {
        object x = Request.Form[s];
    }
}

}
A: 

I believe you are experiencing a viewstate problem. Your dynamic controls are not being persisted. If you haven't already, read Dave Reed's excellent article Truly Understanding Viewstate. Pay particular attention to the section "5. Initializing dynamically created controls programmatically" which applies to the trouble you are experiencing.

Joel Harris
Thanks, I've looked at Dave Reed's posts for both Dynamic Controls and View State and those are very helpful! We've decided to look for a JQuery solution to this problem, so I am updating the original question.
Russ Clark
+1  A: 

The short answer is that you would have to add the controls before the ViewState is initialized.

The video on this site has a nice guide on adding dynamic controls. http://www.asp.net/%28S%28wnmvzu45umnszm455c1qs522%29%29/learn/ajax-videos/video-286.aspx

AcousticBoom
Thanks for the post, I've looked at the video and duplicated the code and that does work. After some discussion internally with our develpoment team, we've decided to look for a JQuery method of solving this problem, so I'm updating the post to ask if anyone has solved this using JQuery.
Russ Clark
+1  A: 

This is probably not a ViewState issue. That may be the first place to look, but after that you need to make sure that your dynamic controls are actually being CREATED on each load.

Generally speaking, the ViewState is only responsible for restoring STATE to existing controls (hence the name). It is not responsible for recreating controls.

Bryan
@Bryan is right. Dave Reed also has an excellent in-depth explanation of dynamic controls. I highly recommend it: http://weblogs.asp.net/infinitiesloop/archive/2006/08/25/TRULY-Understanding-Dynamic-Controls-_2800_Part-1_2900_.aspx
Joel Harris
Thanks, I've looked at Dave Reed's posts for both Dynamic Controls and View State and those are very helpful! We've decided to look for a JQuery solution to this problem, so I am updating the original question.
Russ Clark
+1  A: 

Before choosing a solution for the problem, consider the problem first:

You effectively need to:

1) Duplicate controls/markup on the client-side

2) Obtain these values on the server-side on a postback

3) For each of the added "user controls" on the client-side, add them as children of the first user control on the server side.

I'm not going to give the code, but here are some ideas:

1) Use jQuery's .clone() method (http://api.jquery.com/clone/) to duplicate the markup being rendered by the usercontrol containing the textboxes. Perhaps wrap them in a div without runat="server" to so that you can easily obtain it by ID. You'll probably need to then recursively iterate through the children in the cloned element and append a # to them to avoid any conflicting identifiers. (eg. nameTextBox_1, nameTextBox_2, etc.)

2) On a postback, use the Request.Form collection on the server side to obtain the textbox values. Iterate through it and snag all of the items whose keys start with "nameTextBox_".

3) For each added "user control" on the client side, create the actual user control on the server side, assign to it the values entered in the textboxes, and then add it to the child controls of the first one. This way the state is maintained upon returning to the user.

zincorp
zincorp, I see what you are trying to do, and I have some sample JQuery code (above) that I can use to clone a textbox as you suggest in step 1. I'm having problems when I try to iterate the Request.Form collections to get those values back, can you point me in the right direction?
Russ Clark
Sorry, forgot to specify what the problem is that I am seeing. When I run the code above in debug and inspect the variable s as it iterates, all I get is __VIEWSTATE, __EVENTVALIDATION, and Submit. The Object x variable always has some viewstate in it, but I see no way to decipher its contents.
Russ Clark
Try assigning a name to your input field:<input id="ProjectValue_1" name="ProjectValue_1" type="text" class="projectbox" />
zincorp