redman12
redman12

Reputation: 13

ASP.Net - repeating input boxes on the client side using Repeater

I have the following requirement for creating a user profile in my application:

User should be able to enter multiple phone numbers/email addresses in his profile.
The screen looks somewhat like this:
- By default, on page load a single textbox for phone and email are shown.
- User can click a "+" button to add additional numbers/addresses.
- On clicking the "+" button we need to add another textbox just below the first one. User can add as many numbers/addresses as he wants. On submit, the server should collect all numbers/emails and save it in DB.

I tried using the Repeater control to do this. On page_load I bind the repeater to a "new arraylist" object of size 1. So, this renders fine - user sees a single textbox with no value in it.
When he clicks the "+" button, I ideally want to use javascript to create more textboxes with similar mark-up as the first.

My questions are these:

  1. Can I render the new textboxes anyway using js? I notice that the HTML rendered by the repeater control is somewhat complex (names/ids) etc. and it might not be possible to correctly create those controls on client-side.
  2. If there is a way to do #1, will the server understand that these additional inputs are items in the repeater control? Say, I want to get all the phone numbers that the user entered by iterating over Repeater.DataItems.
  3. Conceptually, is my approach correct or is it wrong to use the Repeater for this? Would you suggest any other approach that might handle this requirement?

Coming from a Struts/JSP background, I am still struggling to get a grip on the .NET way of doing things - so any help would be appreciated.

Upvotes: 1

Views: 7484

Answers (4)

CAbbott
CAbbott

Reputation: 8098

The repeater control may be a bit of overkill for what you're trying to accomplish. It is mainly meant as a databound control for presenting rows of data.

What you can do is to dynamically create the boxes as part of the Page_Load event (C#):

TestInput.aspx :

<form id="form1" runat="server">
    <asp:HiddenField ID="hdnAddInput" runat="server" />
    <asp:Button ID="btnPlus" OnClientClick="setAdd()" Text="Plus" runat="server" />
    <asp:PlaceHolder ID="phInputs" runat="server" />

</form>
<script type="text/javascript">
    function setAdd() {
        var add = document.getElementById('<%=hdnAddInput.ClientID%>');
        add.value = '1';
        return true;
    }
</script>

TestInput.aspx.cs:

protected void Page_Load(object sender, EventArgs e)
{
    if (ViewState["inputs"] == null)
        ViewState["inputs"] = 1;

    if (hdnAddInput.Value == "1")
    {
        ViewState["inputs"] = int.Parse(ViewState["inputs"].ToString()) + 1;
        hdnAddInput.Value = "";
    }

    for (int loop = 0; loop < int.Parse(ViewState["inputs"].ToString()); loop++)
        phInputs.Controls.Add(new TextBox() { ID = "phone" + loop });
}

I ended up using a PlaceHolder to dynamically add the text boxes and a HiddenField to flag when another TextBox needed to be added. Since the IDs were matching, it maintains the ViewState of the controls during each postback.

Upvotes: 4

Dave Swersky
Dave Swersky

Reputation: 34810

Welcome to the hairball that is dynamically-added controls in ASP.NET. It's not pretty but it can be done.

You cannot add new fields dynamically using javascript because the new field would have no representation in the server-side controls collection of the page.

Given that the requirements are that there is no limit to the number of addresses a user can add to the page, your only option is to do "traditional" dynamic ASP.NET controls. This means that you must handle the adding of the control server-side by new-ing a new object to represent the control:

private ArrayList _dynamicControls = new ArrayList();
public void Page_Init()
{
    foreach (string c in _dynamicControls)
    {
        TextBox txtDynamicBox = new TextBox();
        txtDynamicBox.ID = c;
        Controls.Add(txtDynamicBox);
    }
}

public void AddNewTextBox()
{
    TextBox txtNewBox = new TextBox();
    txtNewBox.ID = [uniqueID] //  Give the textbox a unique name
    Controls.Add(txtNewBox);    
    _dynamicControls.Add([uniqueID]);
}

You can see here that the object that backs each dynamically-added field has to be added back to the Controls collection of the Page on each postback. If you don't do this, data POSTed back from the field has nowhere to go.

Upvotes: 2

Guffa
Guffa

Reputation: 700562

  1. No, but you can create input elements similar to what TextBox controls would render.

  2. No. ASP.NET protects itself from phony data posted to the server. You can't make the server code think that it created a TextBox earlier by just adding data that it would return.

  3. The approach is wrong. You are trying to go a middle way that doesn't work. You have to go all the way in either direction. Either you make a postback and add the TextBox on the server side, or you do it completely on the client side and use the Request.Form collection to receive the data on the server side.

Upvotes: 0

Fred
Fred

Reputation: 1234

If you want to user the repeater, I think the easiest way is to put the repeater in a ASP.Net AJAX update panel, add the extra textbox on the sever side.

There are definitely other way to implement this without using repeater, and it maybe much easier to add the textbox using js.

Upvotes: 0

Related Questions