[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

ASP.NET Interacting Client-Side With Repeater Child Controls Using JavaScript/C#

Posted on 2005-04-21
11
Medium Priority
?
11,643 Views
Last Modified: 2013-11-19
Hello,

I have a relatively simple need, but I just can't get things to work. I have a repeater control with several controls in its ItemTemplate. One of those controls is a Checkbox. Another is a Textbox. These controls are rendered client-side as HTML type "checkbox" and type "textarea", respectively.

What I would like to do is add text to the textbox whenever the checkbox is checked--and also make it read-only and grayed-out. In essense, the user will see a checkbox labeled "Skip this question"--and when checking it, the words "User did not want to answer this question" would appear in the textbox and it would immediate become read-only and grayed-out. The textbox needs to be changed to read-only so that the user cannot have the checkbox checked and then go enter text into the textbox (the back end would not know what the intent of the user if the checkbox is checked AND there is custom text in the textbox!). When the user unchecks the checkbox, the textbox text should be cleared, and write-enabled, and "whitened" again.

The problem I have is getting the JavaScript function to interact with the textbox. I tried numerous strategies, from getElementById and the forms collection, but nothing worked for me... To give a summary of my work so far, here is what I know (I'm just not sure how to do it syntactically):

1) I need an onclick() attribute defined for the checkbox that will call a client-side JavaScript function and pass to it the index of the checkbox.
2) The client-side function needs to locate the corresponding textbox (textarea) control and change its readonly and value (text?) properties, depending on whether the checkbox is being checked or is being unchecked.

The textarea controls are being rendered as such:
<textarea name="dlstResponses:_ctl0:txtAnswer" id="dlstResponses__ctl0_txtAnswer" class="textbox" style="height:100px;width:322px;"></textarea>
<textarea name="dlstResponses:_ctl1:txtAnswer" id="dlstResponses__ctl1_txtAnswer" class="textbox" style="height:100px;width:322px;"></textarea>
<textarea name="dlstResponses:_ctl2:txtAnswer" id="dlstResponses__ctl2_txtAnswer" class="textbox" style="height:100px;width:322px;"></textarea>
etc.

The checkbox controls are being rendered as such:
<input id="dlstResponses__ctl0_chkNoAnswer" type="checkbox" name="dlstResponses:_ctl0:chkNoAnswer" onclick="setTexboxVals(0)" />
<input id="dlstResponses__ctl1_chkNoAnswer" type="checkbox" name="dlstResponses:_ctl1:chkNoAnswer" onclick="setTexboxVals(1)" />
<input id="dlstResponses__ctl2_chkNoAnswer" type="checkbox" name="dlstResponses:_ctl2:chkNoAnswer" onclick="setTexboxVals(2)" />
etc.

setTexboxVals() is my current JavaScript function.

*** BELOW DOES NOT WORK ***
*** I KNOW THE SYNTAX IS WRONG; I'M SHOWING PSEUDOCODE ONLY ***

What I need is a JavaScript function that does something like this:

function setTextboxVals(val)
{
       if (checkbox being checked)
                {
      document.getElementById("dlstEssays__ctl" + val + "_txtAnswer").setAttribute("readonly","true");
      document.getElementById("dlstEssays__ctl" + val + "_txtAnswer").setAttribute("backcolor","gray");
      document.getElementById("dlstEssays__ctl" + val + "_txtAnswer").setAttribute("value","User did not want to answer this question");
                }
      else
               {
      document.getElementById("dlstEssays__ctl" + val + "_txtAnswer").setAttribute("readonly","false");
      document.getElementById("dlstEssays__ctl" + val + "_txtAnswer").setAttribute("backcolor","white");
      document.getElementById("dlstEssays__ctl" + val + "_txtAnswer").setAttribute("value","");
                }
      return false;
}

Note that I need to know if the checkbox is being checked or unchecked, and I also need to know how to set the textbox's readonly, backcolor, and value (text) properties.

Any help would be most appreciated.
0
Comment
Question by:Jon500
  • 4
  • 4
  • 3
11 Comments
 
LVL 23

Expert Comment

by:b1xml2
ID: 13835317
it's not so simple. I talk about the theory before i show you what you need to do to make it work.
1. If you recall that the DataGrid has the edit mode where at any one time, only one row is available for editing (by default), that is for very good reasons, as if we expose editable controls throughout every row, we will have to loop through the DataGrid and repopulate the persisted data thereby refreshing the persisted data before rebinding the DataGrid to it.
2. Then there is the client approach and the server approach. If you are looking for simplicity, you use the client code. If you want consistency you'd use the server approach.

I would strongly urge the server approach unless you have very strong reasons against this.
0
 
LVL 33

Expert Comment

by:raterus
ID: 13835474
As long as you can access the checkbox and textbox from codebehind in the ItemCreated or ItemDataBound events of the datagrid, you can use their .ClientID property to correctly reference them as the client would see them.  No reason to be writing all the namingcontainer gobbleygook in your example.  Basically, whan I'd do is this.  Create a global JS function that accepts the client ID's of both the checkbox and textbox.  For each row in ItemCreated, attach an onclick handler to the checkbox to call this function, with both ID's set.  Should work pretty smoothly if done properly, and I don't see any reason not to do it on the clientside.
0
 
LVL 8

Author Comment

by:Jon500
ID: 13835589
b1xml2:
I'm using a repeater control--not a datagrid.

I absolutely must do this client-side. Imagine how ineffective it would be to round-trip after each checkbox click? If the texbox is not grayed-out upon clicking the checkbox, then the user can enter text into the text box as well as have the checkbox checked. As I mentioned, this is not desirable.

raterus:
I see what you're saying, but whether I hard-code the client id's or populate them server-side into the JS code, I still don't have the syntax down. If you do this sort of thing frequently with success, I'd love to see an example.

To reiterate: I am stuck on getting the JavaScript (JS) code to work. I understand server-side code well, and can populate what streams to the client very effectively. I am weak, however, on DOM and JS.

I raised the points to 350. I need someone who can use my pseudocode (JS, at the very least) and provide a working example.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 23

Expert Comment

by:b1xml2
ID: 13835780
aspx
===
<%@ Page language="c#" Codebehind="Repeater.aspx.cs" AutoEventWireup="false" Inherits="b1xml2.ExpertsExchange.CSharp.April.Repeater" %>
<%@ Import Namespace="System.Data"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > 

<html>
  <head>
    <title>Repeater</title>
    <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
    <meta name="CODE_LANGUAGE" Content="C#">
    <meta name=vs_defaultClientScript content="JavaScript">
    <meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">
    <style>
    <!--
    table { border-left:1px solid #000000;border-right:1px solid #000000;border-bottom:1px solid #000000;}
    td {border-top:1px solid #000000;font-family:Verdana;font-size:10pt;}
    input, a {font-family:Verdana;font-size:10pt;}
   
    // -->
    </style>
  </head>
  <body MS_POSITIONING="FlowLayout">
      
    <form id="Form1" method="post" runat="server">
   
<asp:Repeater ID="ExampleRepeater" Runat="server">
<HeaderTemplate>
<table cellpadding="3" cellspacing="0" border="0" width="100%">
<tr>
      <td>ReadOnly</td>
      <td>Comments</td>
      <td>&nbsp;</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
      <td nowrap><asp:CheckBox ID="ReadOnlyCheckBox" Runat="server" Checked='<%# (bool)((DataRowView)Container.DataItem)["Checked"] %>' AutoPostBack="True" OnCheckedChanged="ReadOnlyCheckBox_CheckedChanged"/></td>
      <td nowrap><asp:TextBox ID="CommentsTextBox" Runat="server" Width="95%" Text='<%# (string)((DataRowView)Container.DataItem)["Comments"]%>' /></td>
      <td nowrap align="right"><asp:LinkButton ID="DeleteButton" Runat="server" CommandName="delete" CausesValidation="False">[delete]</asp:LinkButton>&nbsp;&nbsp;&nbsp;</td>
</tr>
</ItemTemplate>
<FooterTemplate>
<tr>
      <td>&nbsp;</td>
      <td nowrap><asp:TextBox ID="CommentsTextBox" Runat="server" Width="95%" /><asp:RequiredFieldValidator ID="CommentsValidator" Runat="server" ControlToValidate="CommentsTextBox"><b title="required" style="color:red;cursor:hand;">***</b></asp:RequiredFieldValidator></td>
      <td nowrap align="right"><asp:LinkButton ID="AddButton" Runat="server" CommandName="add" CausesValidation="True">[add]</asp:LinkButton>&nbsp;&nbsp;&nbsp;</td>
</tr>
</FooterTemplate>
</asp:Repeater>
     </form>
      
  </body>
</html>
0
 
LVL 23

Expert Comment

by:b1xml2
ID: 13835785
aspx.cs
=====
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace b1xml2.ExpertsExchange.CSharp.April
{
      /// <summary>
      /// Summary description for Repeater.
      /// </summary>
      public class Repeater : System.Web.UI.Page
      {
            protected System.Web.UI.WebControls.Repeater ExampleRepeater;
            private static DataTable _table;

            private DataTable TableItems
            {
                  get
                  {
                        if (_table == null)
                        {
                              _table = new DataTable();
                              _table.Columns.Add("Id",typeof(Guid));
                              _table.Columns.Add("Checked",typeof(bool));
                              _table.Columns.Add("Comments",typeof(string));

                              _table.PrimaryKey = new DataColumn [] { _table.Columns[0] };

                        }

                        return _table.Copy();
                  }
            }
            
            private void Page_Init(object sender, EventArgs e)
            {
                  this.ExampleRepeater.ItemCommand += new RepeaterCommandEventHandler(ExampleRepeater_ItemCommand);
                  this.ExampleRepeater.ItemDataBound += new RepeaterItemEventHandler(ExampleRepeater_ItemDataBound);

            }

            private void Page_Load(object sender, System.EventArgs e)
            {
                  // Put user code to initialize the page here
                  if (! IsPostBack)
                  {
                        this.BindData();
                  }
            }


            private void BindData()
            {
                  this.ExampleRepeater.DataSource = PageSource.DefaultView;
                  this.ExampleRepeater.DataBind();
            }

            private DataTable PageSource
            {
                  get
                  {
                        if (ViewState["PageSource"] == null)
                        {
                              ViewState["PageSource"] = TableItems;
                        }

                        return (DataTable)ViewState["PageSource"];
                  }
            }

            public void ReadOnlyCheckBox_CheckedChanged(object sender,EventArgs e)
            {
                  CheckBox readonlyCheckBox = (CheckBox)sender;
                  RepeaterItem item = (RepeaterItem)readonlyCheckBox.Parent;
                  TextBox commentsTextBox = (TextBox)item.FindControl("CommentsTextBox");
                  commentsTextBox.ReadOnly = readonlyCheckBox.Checked;
            }

            #region Web Form Designer generated code
            override protected void OnInit(EventArgs e)
            {
                  //
                  // CODEGEN: This call is required by the ASP.NET Web Form Designer.
                  //
                  InitializeComponent();
                  base.OnInit(e);
            }
            
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {    
                  this.Load += new System.EventHandler(this.Page_Load);
                  this.Init += new EventHandler(Page_Init);

            }
            #endregion

            private void ExampleRepeater_ItemCommand(object source, RepeaterCommandEventArgs e)
            {
                  switch (e.CommandName)
                  {
                        case "add":
                              RefreshData();
                              PageSource.Rows.Add(new object [] {Guid.NewGuid(),false,((TextBox)e.Item.FindControl("CommentsTextBox")).Text});
                        break;
                        case "delete":
                              RefreshData();
                              PageSource.Rows.RemoveAt(e.Item.ItemIndex);
                        break;
                  }
                  BindData();
            }

            private void RefreshData()
            {
                  for(int count=0;count< this.ExampleRepeater.Items.Count;count++)
                  {
                        RepeaterItem item = this.ExampleRepeater.Items[count];
                        TextBox commentsTextBox = (TextBox)item.FindControl("CommentsTextBox");
                        CheckBox readonlyCheckBox = (CheckBox)item.FindControl("ReadOnlyCheckBox");
                        DataRow row = PageSource.Rows[count];
                        row["Checked"] = readonlyCheckBox.Checked;
                        row["Comments"] = commentsTextBox.Text;
               
                  }
            }

            private void ExampleRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
            {
                  switch (e.Item.ItemType)
                  {
                        case ListItemType.Item:
                        case ListItemType.AlternatingItem:
                              DataRowView rowView = (DataRowView)e.Item.DataItem;
                              TextBox commentsTextBox = (TextBox)e.Item.FindControl("CommentsTextBox");
                              commentsTextBox.ReadOnly = (bool)rowView["Checked"];
                        break;

                  }

            }
      }
}
0
 
LVL 23

Expert Comment

by:b1xml2
ID: 13835789
The pasted code in full uses the server-side approach.
0
 
LVL 33

Accepted Solution

by:
raterus earned 1400 total points
ID: 13836598
Here is the javascript to do what you are after, without getting the server involved.  Just pass it id's of the controls to modify.

<script language="javascript">

function setTextboxVals(chkID, txtID)
{
      var chk = document.getElementById(chkID);
      var txt = document.getElementById(txtID);

      if (chk.checked == true)
      {
            txt.disabled = true;
            txt.value = "User did not want to answer this question";
      }
      else
      {
            txt.disabled = false;
            txt.value = "";
      }            
      
      return true;
}
</script>

<input type="checkbox" id="chkTest" onClick="setTextboxVals(this.id,'txtTest');" />
<textarea id="txtTest"></textarea>
0
 
LVL 8

Author Comment

by:Jon500
ID: 13838989
I need to digest the responses. I'll post my reply later tonight or early tomorrow.
0
 
LVL 8

Author Comment

by:Jon500
ID: 13839911
b1xml2:
Thank you for your comments. However, your code does not compile as posted. Also, I specified that I was seeking an exclusively client-side solution.
0
 
LVL 8

Author Comment

by:Jon500
ID: 13839940
raterus:
Your solution is exactly what I was seeking. Thank you!!!

I did not know about .ClientID until you mentioned it to me. It is EXTREMELY USEFUL whenever JavaScript is required! I am embarrassed to admit that I was going to hard-code the ID's into the JavaScript function, and vary only the Repeater (datasource) index as needed. .ClientID is obviously the correct solution because hard-coding would create a maintanence nightmare should the names ever change on the server.

To help others who may read this thread, I wanted to explain how I handled the server side...

In the ItemDataBound function of my Repeater control, I first assign a variable to the CheckBox and TextBox controls:

System.Web.UI.WebControls.TextBox txtAnswer = (System.Web.UI.WebControls.TextBox)(e.Item.FindControl("txtAnswer"));
System.Web.UI.WebControls.CheckBox chkNoResponse = (System.Web.UI.WebControls.TextBox)(e.Item.FindControl("chkNoResponse"));

Then I add the "onclick" function call to the CheckBox's HTML (also in the ItemDataBound function) as follows:

chkNoResponse.Attributes.Add("onclick","setTextboxVals('" + chkNoResponse.ClientID.ToString() +
                              "', '" +
                              txtAnswer.ClientID.ToString() +
                              "');");

Notice that I am surrounding the arguments to the "setTextboxVals" function with single quotes--they're needed by JavaScript.

I have accepted your answer. It's a very elegant solution, and I thank you for your help!

Cheers,
-- Jon
0
 
LVL 33

Expert Comment

by:raterus
ID: 13843407
Glad I could help!
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Styling your websites can become very complex. Here I'll show how SASS can help you better organize, maintain and reuse your CSS code.
Originally, this post was published on Monitis Blog, you can check it here . In business circles, we sometimes hear that today is the “age of the customer.” And so it is. Thanks to the enormous advances over the past few years in consumer techno…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…
Suggested Courses

873 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question