We have a checkbox that is initially disabled and checked. It is then enabled on the client side through javascript. If the user then unchecks the box and presses the button to invoke a postback, the state of the checkbox remains as checked on the server side. This is obviously undesirable behaviour. Here is an example.
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="testcb.aspx.cs" Inherits="ESC.testcb" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<script type="text/javascript">
function buttonClick() {
var cb = document.getElementById('<%= CheckBox1.ClientID %>');
cb.disabled = false;
cb.parentNode.disabled = false;
}
</script>
<div>
<asp:CheckBox ID="CheckBox1" runat="server" Checked="true" Enabled="false" />
<asp:Button ID="Button1" runat="server" Text="Button" OnClientClick="buttonClick(); return false;" />
<asp:Button ID="Button2" runat="server" Text="Button2" OnClick="button2Click" />
</div>
</form>
</body>
</html>
And the Server-side code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace ESC
{
public partial class testcb : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void button2Click(object sender, EventArgs e)
{
string h = "";
}
}
}
So we break at the "string h" line and check the value of CheckBox1.Checked. It is true, even if it is unchecked on the form.
This is a known problem with ASP.NET - for some reason ASP.NET won't update a checkbox on postback if it was disabled during page load and not checked for postback. I don't know exactly why that is though - if you make the checkbox unselected by default and select it, the value is changed on the server correctly.
The workaround is to add a hidden field to the page that represents the state of the checkbox, then update the field's value to "ON" or "OFF" for example, whenever the checkbox is clicked.
Then on the server you check the value of the hidden field, not the checkbox itself, as the hidden field is always posted.
I had a similar problem to this where the Checked property of the CheckBox object was not being updated correctly, to get the actual posted value you can check:
Request.Form[CheckBox1.UniqueID]
it will be 'on' if the box is checked and null if not.
Since you're already using Javascript to manipulate the controls state in the browser, I suggest you just disable the checkbox on the page load event in stead. Then your postbacks will work just fine...
<head>
<script type="text/javascript">
function buttonClick() {
var cb = document.getElementById('<%= CheckBox1.ClientID %>');
cb.disabled = false;
cb.parentNode.disabled = false;
}
</script>
</head>
<body onload="document.getElementById('<%= CheckBox1.ClientID %>').disabled = true;">
<form id="form1" runat="server">
<div>
<asp:checkbox id="CheckBox1" runat="server" checked="true" />
<asp:button id="Button1" runat="server" text="Button" onclientclick="buttonClick(); return false;" />
<asp:button id="Button2" runat="server" text="Button2" onclick="button2Click" />
</div>
</form>
</body>
I may not understand the problem correctly, but can't you just use the Form from the Request to retrieve the CheckBox value? So in button2Click() in the code behind file you'd do this:
Request.Form[CheckBox1.UniqueID]
You can use something like this.
if ((Request.Params["Checkbox1"] ?? "").ToString() == "on")
If it isn't checked it won't pass it in the first place, but this should account for that.
Here is an alternative solution if you need to avoid recompiling your source code.
It just enables the checkbox for a split second before submitting the form.
1: Add the following parameter to your submit button:OnClientClick="EnableCheckbox()"
2: Add this simple function somewhere on the page to enable it
<script>
function EnableCheckbox() {
document.getElementById("<%=chkMyCheckbox.clientID %>").disabled = false;
}
</script>
Related
Here is the problem. I have a radiobutton group (two radiobuttons).
These guys are initialy disabled. When the user clicks a checkbox, I dynamically enable radiobuttons in javascript by setting rbtn.disabled = false; and doing the same for it's parent (span element) so it correctly works in IE.
The problem is that these dynamically enabled radiobuttons are not returned on postback (I see rbtn.Checked == false on serverside and request.form does not contain proper value).
Why is this happening? Is there another fix except for a workaround with hidden fields?
Expected answer decribes post-back policy, why/how decides which fields are included in postback and fix to this problem.
Before doing the submit, remove the disabled attribute from the radio buttons like this:
document.getElementById("rbtnID").removeAttribute("disabled");
Note that removeAttribute can be buggy in IE, and IE also implements a second attribute for case sensitivity, see MSDN article.
There is also removeAttributeNode which removes the entire attribute node, but it takes the node itself as the parameter instead of the name.
var disabledNode = element.getAttributeNode('disabled');
element.removeAttributeNode(disabledNode);
So give these a shot and let me know how they play out!
I know the following code is not neat, but it gets the job done (if I understand the problem correctly). I copy/paste here the whole file contents to make it easier for you to play with it. Just create a web form named WebForm1 and paste these;
in .aspx file:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<script type="text/javascript">
function enable(sender) {
if (sender.checked) {
document.getElementById('<%= RadioButton1.ClientID %>').removeAttribute('disabled');
document.getElementById('<%= RadioButton2.ClientID %>').removeAttribute('disabled');
}
else {
document.getElementById('<%= RadioButton1.ClientID %>').disabled = true;
document.getElementById('<%= RadioButton2.ClientID %>').disabled = true;
}
}
</script>
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:CheckBox ID="CheckBox1" runat="server" onclick="enable(this)" />
<asp:RadioButton ID="RadioButton1" runat="server" Text="1"
Enabled="false" />
<asp:RadioButton ID="RadioButton2" runat="server" Text="2"
Enabled="false" />
<asp:Button ID="Button1" runat="server" Text="Button"
onclick="Button1_Click1" />
<asp:Label ID="Label1" runat="server" Text="" />
</form>
</body>
</html>
in .aspx.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class WebForm1 : System.Web.UI.Page
{
static readonly string GROUP_NAME = "RadioButtonGroup";
protected void Page_Load(object sender, EventArgs e)
{
RadioButton1.GroupName = GROUP_NAME;
RadioButton2.GroupName = GROUP_NAME;
if (IsPostBack)
{
if (CheckBox1.Checked)
{
RadioButton1.Enabled = true;
RadioButton2.Enabled = true;
if (Request.Params[GROUP_NAME] == RadioButton1.ID)
{
RadioButton1.Checked = true;
}
else if (Request.Params[GROUP_NAME] == RadioButton2.ID)
{
RadioButton2.Checked = true;
}
}
}
}
protected void Button1_Click1(object sender, EventArgs e)
{
if (Request.Params[GROUP_NAME] == RadioButton1.ID)
{
Label1.Text = "1 is selected";
if (Request.Params[GROUP_NAME] == RadioButton2.ID)
{
Label1.Text += "and 2 is selected";
}
}
if (Request.Params[GROUP_NAME] == RadioButton2.ID)
{
Label1.Text = "2 is selected";
}
}
}
}
I haven't had a chance to test this myself, but I'm guessing (if your using ASP.net), that your disabling the radio buttons via the ASP.net server-side code i.e via a server side control.
And then renabling them using javascript?
I think perhaps that the server-side still believes they are disabled - I'm not 100% why without digging futther (something in the page lifecycle somewhere).
Perahaps a quick solution would be instead of disabling the radio buttons via server-side, instead disable them in javascript when the page loads? i.e. doing the disabling and enabling in javscript.
Before submitting the page set the disabled property of the radios buttons to false. In the code behind read the radio button value using Request.Form["radioButtonName"]. This will give you the value of the radio button which is checked.
Example:
Let say the radio button list name is radioButton1 with 2 radio buttons. When it renders on the page the radio buttons will have the same name say ctl0$radioButton1. Anyways it depends on the nesting of your page. You can get this name using radioButton.UniqueID.
When the page is submitting through any action on the page execute the below javascript which will set the disabled property of the radio button to false.
document.getElementById("radioButton1ItemCliendId").disabled = false;
//If you want to check this radio button then
document.getElementById("radioButton1ItemCliendId").checked = true;
On the server side postback event handler you have to use Request.Form[radioButton1.UniqueID] to get this radio buttons value. It will give the radio buttons value which is checked.
I have an aspx page which has 18 (yes 18) dropdown lists and 18 text boxes. Each dropdown needs to be selected and each textbox needs to be filled. Dragging and dropping required field validators on these 36 controls and maintaining them is a painful task and does not seem to be the logical option as all I need is for the user to select a value from the dropdown.
Is there anyway I can loop through all these dropdown controls and textbox controls, check if they are empty and display warnings to users accordingly? Client-side validation solution or server side validation solution is fine with me.
Use a CustomValidator and have a client script function that makes sure every text box/drop down has a value.
One suggestion is to loop through all the controls on the page, use recursive function to dynamically bind RequiredFieldValidator to the found controls. You can tweak my code to suit your needs.
This code has some drawbacks though:
Use control.ID instead of associated label text
Adding RequiredFieldValidator to the page.controls will modify its ControlCollection. This will break the foreach method. Thus, I can only add RequiredFieldValidator to Panel instead.
.aspx
<asp:Panel ID="pnlValidation" runat="server">
</asp:Panel>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:TextBox ID="TextBox3" runat="server"></asp:TextBox>
<br />
<asp:DropDownList ID="DropDownList1" runat="server" />
<asp:DropDownList ID="DropDownList2" runat="server" />
<asp:DropDownList ID="DropDownList3" runat="server" />
<br />
<asp:Button ID="Button1" runat="server" Text="Button" />
.cs
protected void Page_Load(object sender, EventArgs e)
{
AddValidator(this);
}
private void AddValidator(Control ctrl)
{
if (ctrl is TextBox || ctrl is DropDownList)
{
RequiredFieldValidator rfv = new RequiredFieldValidator();
rfv.ControlToValidate = ctrl.ID;
rfv.Display = ValidatorDisplay.Dynamic;
rfv.ErrorMessage = ctrl.ID + " is required<br />";
pnlValidation.Controls.Add(rfv);
}
foreach (Control subctrl in ctrl.Controls)
AddValidator(subctrl);
}
If you are dynamically generating the textboxes and dropdownlists, you would probably want to dynamically generate the validation controls as well, but if all the drop down lists and textboxes are static you can use the following:
Use a CustomValidator Web Control, write client side javascript method that checks all the properties of the drop down lists and the textboxes and configure the web control's ClientValidationFunction with the function and set EnableClientScript=true. Also, b/c not all users have javascript enabled, plus to be sure as it is best practice, always also create a server side validation function as well and call Page.IsValid() on the submit action.
.aspx Sample Code
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs"
Inherits="Default2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script language="javascript" type="text/javascript">
function ValidateMe(sender, args) {
var txt = document.getElementById("txt");
if (txt.value != "")
args.IsValid = true;
else
args.IsValid = false;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:TextBox id="txt" runat="server" />
<asp:CustomValidator ClientValidationFunction="ValidateMe" ID="custval"
runat="server" ErrorMessage="Fail" onservervalidate="custval_ServerValidate" />
<asp:Button ID="btn" runat="server" Text="push" onclick="btn_Click1" />
</form>
</body>
</html>
c# codebehind sample code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Globalization;
using System.Threading;
public partial class Default2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
}
}
protected void btn_Click1(object sender, EventArgs e)
{
if (Page.IsValid)
{
btn.Text = "PASS";
}
else
{
btn.Text = "FAIL";
}
}
protected void custval_ServerValidate(object source, ServerValidateEventArgs args)
{
if (txt.Text != "")
custval.IsValid = true;
else
custval.IsValid = false;
}
}
According to the info in:
Which values browser collects as a postback data?
the value of the HTML input button is sent in a post back. I'm testing in ASP.NET with IE and I am not finding this to be the case.
The markup for my test case is:
<%# Page Language="VB" AutoEventWireup="false" CodeFile="Test.aspx.vb" Inherits="Test" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>test postback</title>
<script type="text/javascript">
function doTest() {
var button = document.getElementById("btnTest");
button.value = "new-value";
alert("button contents = " + button.value);
return true;
}
</script>
</head>
<body>
<form id="myForm" runat="server">
<div>
<asp:Panel ID="pnlTest" runat="server"
DefaultButton="btnTest">
Textbox:
<asp:TextBox ID="txtTest" runat="server" />
<asp:Button ID="btnTest" runat="server"
Text="change" OnClientClick="doTest()" />
</asp:Panel>
</div>
</form>
The code behind is:
Partial Class Test
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
txtTest.Text = btnTest.Text
End Sub
End Class
My result is that the value of the input button is always "change" when the browser loads the page, but I was expecting it to be "new-value" after postback. The Javascript doTest() function is changing the value when the button is clicked.
Is there something more I'm supposed to do for ASP.NET or IE to get the input button value posted back? Or is the information about this functionality
wrong?
In a case like this I would probably use:
<input type="button" ID="btnTest" runat="server" onclick="doTest()" value="change" />
Note the runat="server".
While asp:button probably renders similarly, if what you really want it an HTML button input, you can use that. Yes, ASP.NET will pick up the value on the server side.
Also, do a view source and make sure the ASP.NET panel is not munging up the ID of the input. More generally, have you tested this without the asp:panel tag? I wonder if that affects anything.
I believe IE just hates input submits....
But you should also know...
ASP uses viewstate to ensure there is no tampering with server controls. The value of the submit button is stored in the view state and most likely the only way to modify the value of it is to use the ASP.NET JS API.
More commonly you see this problem with <selects> (Options added to by javascript lost in postback), but <input type="submit" /> is very similar
It's not that it's not being set, but the javascript sets the value, which gets reset back to "change" on the postback. If you're looking for a button that works with your javascript, use the client input control:
<input type="button" ID="btnTest" onclick="doTest()" />
Otherwise, if you want a server control, you should set btnTest.Text on the server side.
You are using the wrong id for the button. ASP.NET gives each control a unique id. It is made up of all the ids in the chain to your control.
Therefore your button probably has an id something like ctl00_pnlTest_btnTest. This is why your JavaScript is not setting the buttons text.
view source in your browser to see the actual ID of the control and adjust your JavaScript accordingly.
From code you can get the actual ID used in the page with the ClientID property. So you could change your JavaScript to:
var button = document.getElementById("<%= btnTest.ClientID %>");
Just tried Marc's solution like this:
<script type="text/javascript">
function doTest() {
var button = document.getElementById("btnTest1");
button.value = "new-value";
alert("button contents = " + button.value);
return true;
}
</script>
<input type="submit" id="btnTest1" name="btnTest1" value="Submit 1" runat="server" onclick="doTest()" />
When I posted back the Load event still had Submit 1 as the value of the button. You could use a hidden field, set that value with the button in JS and post back. That does in fact work.
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>test postback</title>
<script type="text/javascript">
function doTest() {
var button = document.getElementById("btnTest1");
button.value = "new-value";
alert("button contents = " + button.value);
var hdn = document.getElementById("hdnTextboxName");
hdn.value = button.value;
return true;
}
</script>
</head>
<body>
<form id="myForm" runat="server">
<div>
<asp:Panel ID="pnlTest" runat="server" DefaultButton="btnTest">
Textbox:
<asp:TextBox ID="txtTest" runat="server" /><asp:HiddenField ID="hdnTextboxName" runat="server" ClientIDMode="Static" />
<asp:Button ID="btnTest" runat="server" Text="change" OnClientClick="doTest()" ClientIDMode="Static" />
</asp:Panel>
</div>
</form>
</body>
</html>
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
txtTest.Text = hdnTextboxName.Value
End Sub
<asp:RadioButtonList ID="RdoBtnHasNotified" runat="server" RepeatDirection="Horizontal" AutoPostBack="True" OnSelectedIndexChanged="RdoBtnHasNotified_SelectedIndexChanged">
<asp:ListItem Value="1">Yes</asp:ListItem>
<asp:ListItem Value="0" Selected="True">No</asp:ListItem>
</asp:RadioButtonList>
<asp:TextBox ID="TxtHowNotified" runat="server" TextMode="MultiLine" MaxLength="100"></asp:TextBox>
I want to enable the TextBox by clicking on the RadioButtonList, without using autopostback=true. How can I do this with JavaScript?
You can use jQuery to manipulate input's enabled state (HTML translation for TextBox) or you can use ASP.NET Ajax so you can set both controls inside of update panel in this case you won't see page being reloaded on postback which must happen in order for you to change status of TextBox on some other event.
Tbh i would go with ASP.NET Ajax because my experience shows that jQuery does not work that well with ASP.NET controls when it comes to complex stuff ie. ASP.NET uses javascript for event activation which can cause either jQuery or ASP.NET not to work as you may expected.
Good luck with update panels...
Using jQuery, you can have a fairly custom result by hooking in to the changes on the radio buttons...
$("#<%= RdoBtnHasNotified.ClientID %> > input[type=radio]").change(function(){
// this function is called whenever one of the radio button list's control's change
// the $(this) variable refers to the input control that triggered the event
var txt = $("#<%= TxtHowNotified.ClientID %>");
if($(this).val()=="1") {
txt.removeAttr("disabled");
} else {
txt.attr("disabled", true);
}
});
Each ListItem renders a radio button with the same name parameter; I would suggest running the app and looking at the generated source to get an idea of what you need to do to listen for the radio button events. Essentially the ID of the radio button list is the name parameter, so you can get the group of radio buttons as (using JQuery):
$("input[name='<%= rbl.ClientID%>']").click(function() {
var tb = $("#textboxid");
//do something here; this points to the radio button
});
HTH.
Here you go:
<%# Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void RdoBtnHasNotified_PreRender(object sender, EventArgs e)
{
foreach (ListItem item in RdoBtnHasNotified.Items)
item.Attributes.Add("onclick", string.Format("toggleTextBox(this,'{0}');", TxtHowNotified.ClientID));
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type="text/javascript">
function toggleTextBox(radioButton, textBoxId) {
document.getElementById(textBoxId).disabled = radioButton.value != "1";
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:RadioButtonList ID="RdoBtnHasNotified" OnPreRender="RdoBtnHasNotified_PreRender"
runat="server" RepeatDirection="Horizontal">
<asp:ListItem Value="1">Yes</asp:ListItem>
<asp:ListItem Value="0" Selected="True">No</asp:ListItem>
</asp:RadioButtonList>
<asp:TextBox ID="TxtHowNotified" runat="server" TextMode="MultiLine" MaxLength="100" Enabled="false"></asp:TextBox>
</div>
</form>
</body>
</html>
Write the code in the following way
<script type="text/javascript">
$(document).ready(function() {
$("input[name='RdoBtnHasNotified']").change(function() {
$("input[name='RdoBtnHasNotified']:checked").val() == '1' ? $('#TxtHowNotified').removeAttr("disabled") : $('#TxtHowNotified').attr('disabled', 'true');
});
});
</script>
and also disable the textbox (Enabled="false") since initialy the value of the "RdoBtnHasNotified" is "No".
$('#<%= RdoBtnHasNotified.ClientID %> > input[type=radio]').click(function()
{
var txtbox = $('#<%= TxtHowNotified.ClientID %>');
if($(this).val() == '1')
{
document.getElementById('#<%= TxtHowNotified.ClientID %>').disabled = false;
}
else
{
document.getElementById('#<%= TxtHowNotified.ClientID %>').disabled = true;
}
});
I think using change event will not fire in IE.
Hi I'm facing a weird problem that only happens in FF. I have a TextBox control with OnTextChanged handler. The event handler is working fine most of the time, but when the user changed the text and press Enter in FF, the OnTextChanged event is called twice. I observed the problem in Firebug that the first request is actually canceled because of the second event.
Test.aspx
<%# Page Language="C#" AutoEventWireup="True" CodeFile="~/Test.aspx.cs" Inherits="T.Test" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Custom TextBox - OnTextChanged - C# Example</title>
</head>
<body>
<form id="Form1" method="post" runat="server">
<asp:ScriptManager runat="server" ID="SM">
</asp:ScriptManager>
<h3>Custom TextBox - OnTextChanged - C# Example</h3>
<asp:UpdatePanel runat="server" ID="Panel1">
<ContentTemplate>
<asp:Panel runat="server" ID="Panel2">
<asp:TextBox ID="TextBox1" AutoPostBack="true" OnTextChanged="OnTextChanged" runat="server">Hello World!
</asp:TextBox>
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
Test.aspx.cs
using System;
using System.Web.UI;
namespace T
{
public partial class Test : Page
{
protected void OnTextChanged(object sender, EventArgs e)
{
var a = 0;
}
}
}
Put a break point # var a, and you'll be able to see that after changing text and press enter in FF (v3.5.7), the OnTextChanged event is invoked twice.
So my question is, what's the best way to properly handle OnTextChanged event so that hitting enter in the textbox doesn't trigger double postback.
Regards,
I don't know why it's isolated to FireFox, but if you remove the AutoPostBack property, that will solve the problem.
There is also an explanation here of why it's posting back twice.
I know its an old thread but maybe helpful for others.
I had the same issue when validating the text entered. I was getting 2 events fired so I put this script at the top of the page which causes the enter to just tab to the next control instead of submitting the form. The text box remained the same AutoPostBack="true" OnTextChanged="xxx_TextChanged"
''''
<script type="text/javascript">
$('body').on('keydown', 'input, select', function (e) {
if (e.key === "Enter") {
var self = $(this), form = self.parents('form:eq(0)'), focusable, next;
focusable = form.find('input,a,select,button,textarea').filter(':visible');
next = focusable.eq(focusable.index(this) + 1);
if (next.length) {
next.focus();
} else {
form.submit();
}
return false;
}
});
</script>
''''