ASP javascript radiobutton enable disable not included in postback ajax - asp.net

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.

Related

How to stop dropdownlists where autopostback true, from posting to a new page set in postbackurl of button ASP.NET

The page performs as intended locally, the problem is when I upload to windows server and access it from there.
I have 2 to 3 dropdownlists displayed (depending on whats selected in the first dropdownlist)....
The first 2 dropdownlists where autopostback is set to true, will autopostback to the same page (intended performance). However, after I click the button within the form, and go back to original page, whenever there is a selectedindexchanged event on those dropdownlists, those dropdownlists are not autopostback to the same page anymore, they will now post to the postbackurl declared in the button (this is unintended and not the desired results)
How can I get those dropdownlists to stop from posting to new page on selectedindexchanged after I click the button and go back to original page?
Again, the dropdownlists do not autopostback to a new page until I click the button and then go back to that original page. At that point they then post to the postbackurl that is declared in the button. I don't understand why this is happening.
<asp:Content ID="Content1" ContentPlaceHolderID="MainContentPlaceHolder1" runat="server">
<div style="text-align: center">
<asp:Label ID="Label1" runat="server"></asp:Label>
<form id="form1" runat="server">
<asp:DropDownList ID="toolGroupDropDown" runat="server" AutoPostBack="true" OnSelectedIndexChanged="toolgroupddl_SelectedIndexChanged">
</asp:DropDownList>
<asp:DropDownList ID="sizeDropDown" runat="server" AutoPostBack="true" OnSelectedIndexChanged="sizeddl_SelectedIndexChanged" Visible="False">
</asp:DropDownList>
<asp:DropDownList ID="attDropDown" runat="server" Visible="False">
</asp:DropDownList><br />
<asp:Button ID="seeToolsButton" runat="server" Text="See Tools" Visible="False" PostBackUrl="/products" />
</form>
</div>
</asp:Content>
Here is some code-behind, not sure if this is relevant though...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
namespace Testing
{
public partial class WebForm12 : System.Web.UI.Page
{
public string listing;
public string attsize;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
FillDropDown();
}
else
{
System.Diagnostics.Debug.WriteLine("postback occured");
}
}
protected void toolgroupddl_SelectedIndexChanged(object sender, EventArgs e)
{
listing = toolGroupDropDown.SelectedValue;
sizeDropDown.DataSource = this.GetSizeRecords();
sizeDropDown.DataTextField = "groups";
sizeDropDown.DataValueField = "groups";
sizeDropDown.DataBind();
sizeDropDown.Visible = true;
seeToolsButton.Visible = true;
toolGroupDropDown.Items.Remove(toolGroupDropDown.Items.FindByValue(""));
if (toolGroupDropDown.SelectedValue != "END")
{
sizeDropDown.AutoPostBack = false;
attDropDown.Visible = false;
sizeDropDown.Items.Insert(0, new ListItem("Choose Your Size", ""));
}
else
{
attDropDown.Visible = true;
sizeDropDown.AutoPostBack = true;
sizeDropDown.Items.Insert(0, new ListItem("Choose Your Size", ""));
}
}
protected void sizeddl_SelectedIndexChanged(object sender, EventArgs e)
{
if (toolGroupDropDown.SelectedValue == "END")
{
attDropDown.DataSource = this.GetAtts(attsize);
attDropDown.DataTextField = "NoOfAtts";
attDropDown.DataValueField = "NoOfAtts";
attDropDown.DataBind();
attDropDown.Visible = true;
}
else
{
attDropDown.Visible = false;
}
}
}
}
I only posted the code-behind that seemed relevant. Nothing else in the code relates to the question at hand.
The problem is page changing the action attribute. At Html level, initially you have:
<form method="post" id="form1" action="./WebForm12">
So dropdowns correctly post back to WebForm12. But when you press the button.
<asp:Button ID="seeToolsButton" runat="server" PostBackUrl="/products" />
The page does two things using Javascript:
Change the action attribute of the form to "/products".
Post the form.
When you navigate back in your browser, the form looks like this
<form method="post" id="form1" action="/products">
But now, dropdowns will post the form to /products, not WebForm12.
Solution: One way to fix that is adding this script to your aspx file
<script type="text/javascript">
window.onpageshow = function () {
form1.action = "./<%=System.IO.Path.GetFileName(Request.Url.AbsolutePath)%>";
};
</script>
However if your browser does not support onpageshow (e.g. IE10 or older), then you'd rather attach the function to click event of the dropdowns.

Keep a value accessible in Page.Init between postbacks in asp.net

Ok, I've already learned that in order to keep the dynamic (created) controls and their viewstate in asp.net we must (re)create them in the Page init event, so they already exist within the page's control hierarchy before the view state is loaded.
As it says in this article.
There is no problem to achieve this behaviour if the criteria to create these controls is outside the web environment, for example a database. But what should I do if what I use to decide how many dynamic controls I have to create is actually a value that is in the controls?
I try to explain it with an example, maybe it's clearer:
Let's say that we have a textbox and two buttons. In the textbox I write the number of how many dynamic controls I want to create, for example 4 checkbox. When I hit the button1 the controls should be created. No problem. Then I check some checkboxes and hit the button2 just to fire a postback. Now I should recreate the controls in the page init event, like we said before, in order to maintain the controls and their state.
And here comes the problem. Because of I'm in the init stage I have no viewstate so I'm no able to access the value in the textbox that tells me how many dynamic checkbox should I create.
I thought that storing the value in the session object would do the trick, but it doesn't. The session object is no accessible as well.
Where can I save the value that it'll be accessible from the init event too?
Thanks and sorry for the long post!
First thing - textbox value is not stored/retrieved from view state, you cannot get textbox value from viewstate.
Coming to actual problem, here is the sequence of (imp) events init -> load view state -> bind postback data -> page load. You can retrieve textbox value only after bind postback data event (which actually takes posted data and binds to the textbox control).
In init only option is to use Request.Form{"textboxid"] to get the textbox value.
You are on the right track.
If you use TextBox, you do not need another ViewState to keep track of how many controls has been created, because TextBox control has its own ViewState already.
You can use either Page_Init or Page_Load to load control back.
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs"
Inherits="WebApplication2010.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">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox runat="server" ID="NumberTextBox" />
<asp:Button runat="server" ID="CreateControlButton"
OnClick="CreateControlButton_Click"
Text="Create Control" />
<br />
<asp:PlaceHolder runat="server" ID="PlaceHolder1"></asp:PlaceHolder>
</div>
</form>
</body>
</html>
using System;
using System.Web.UI;
namespace WebApplication2010
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
int ids;
if (Int32.TryParse(NumberTextBox.Text, out ids))
{
for (int i = 0; i < ids; i++)
{
Control ctrl = Page.LoadControl("WebUserControl.ascx");
ctrl.ID = i.ToString();
PlaceHolder1.Controls.Add(ctrl);
}
}
}
}
protected void CreateControlButton_Click(object sender, EventArgs e)
{
}
}
}
<%# Control Language="C#" AutoEventWireup="true"
CodeBehind="WebUserControl.ascx.cs"
Inherits="WebApplication2010.WebUserControl" %>
<asp:CheckBox runat="server" ID="CheckBox1" />
<asp:Button runat="server" ID="Button1" OnClick="Button_Click"
Text="Post Back" />
<asp:Label runat="server" ID="Label1" />
<br />
using System;
namespace WebApplication2010
{
public partial class WebUserControl : System.Web.UI.UserControl
{
protected void Button_Click(object sender, EventArgs e)
{
Label1.Text = " This control was posted back.";
}
}
}
This is the common paradox with page lifecycle when you work with code behind. For example, you save the editing customerid in viewstate but controls need to bind on init to be able to read their posted values.
Best real life solution is to do what bound controls do on postback, call explicilately the LoadPostBackData on IPostBackDataHandler interface that all controls implement, after you have created them in Page Load event.
You should create an extension method for Controls and call it when needed:
control.DataBind();
control.LoadPostedData(); // extension method

handling enter press in <asp:textbox

I have an asp.net textbox which I want to use as a search box.
I wasn't planning on having a button, just allowing the user to type their search keywords into the textbox and press enter.
<div id="search-bar">
<asp:TextBox ID="txtSearch" runat="server" ></asp:TextBox>
</div>
How can I get the "enter press" to call a method, or post back the page with keywords in URL parameters, e.g. search.aspx?keywords=this&that?
Set AutoPostback to true if you want to call a function in codebehind OnTextChanged. This will occur if the Textbox loses focus(f.e. Tab-key) or Enter-Key is pressed.
There are other ways you can set a default button using the form object DefaultButton property or the DefaultButton property of a panel, but I have found them to be unreliable in the past in various browsers so usually I rely on javascript, if you don't want the button visible you can just set the visible property to false.
The only downside to this code is you have to turn off event validation with a page directive, but it should fire off click events, and trigger validators and all that.
Here is an example the code that we use. Normally I would put the register function in a utility class, but for this example it is in the page code.
<%# Page Language="C#" EnableEventValidation="false" %>
<script runat="server">
protected void cmdSubmit1_Click(object sender, EventArgs e)
{
litValue.Text = "Value 1 - You entered: " + txtValue1.Text;
}
protected void cmdSubmit2_Click(object sender, EventArgs e)
{
litValue.Text = "Value 2 - You entered: " + txtValue2.Text;
}
/// <summary>
/// This function registers what button is clicked based on whatever control currently has focus
/// so for example if the user password field has focus then you can cause the enter button to click
/// if the enter key is pressed This works with ie and firefox as far as I know
/// </summary>
/// <param name="ControlWithFocus"></param>
/// <param name="ControlToClick"></param>
private void RegisterDefaultButton(System.Web.UI.Control ControlWithFocus, System.Web.UI.Control ControlToClick)
{
PostBackOptions p = new PostBackOptions(ControlToClick);
p.PerformValidation = true;
if (ControlToClick is Button)
{
p.ValidationGroup = ((Button)ControlToClick).ValidationGroup;
}
else if (ControlToClick is ImageButton)
{
p.ValidationGroup = ((ImageButton)ControlToClick).ValidationGroup;
}
else if (ControlToClick is LinkButton)
{
p.ValidationGroup = ((LinkButton)ControlToClick).ValidationGroup;
}
p.RequiresJavaScriptProtocol = false;
AttributeCollection a = null;
if (ControlWithFocus is HtmlControl)
{
a = ((System.Web.UI.HtmlControls.HtmlControl)ControlWithFocus).Attributes;
}
else if (ControlWithFocus is WebControl)
{
a = ((System.Web.UI.WebControls.WebControl)ControlWithFocus).Attributes;
}
if (a != null)
{
a["onKeyDown"] = string.Format("if (event.keyCode == 13) {{{0}}}"
, ControlToClick.Page.ClientScript.GetPostBackEventReference(p));
}
}
protected void Page_Load(object sender, EventArgs e)
{
RegisterDefaultButton(txtValue1, cmdSubmit1);
RegisterDefaultButton(txtValue2, cmdSubmit2);
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
</head>
<body>
<form id="form1" runat="server">
Enter Value 1: <asp:TextBox ID="txtValue1" runat="server"></asp:TextBox>
<br />
Enter Value 2: <asp:TextBox ID="txtValue2" runat="server"></asp:TextBox>
<br />
<asp:Literal ID="litValue" runat="server"></asp:Literal>
<asp:LinkButton ID="cmdSubmit1" runat="server" Visible="false" OnClick="cmdSubmit1_Click">Hidden Button 1</asp:LinkButton>
<input id="cmdSubmit2" runat="server" visible="false" type="button" value="Hidden Button 2" onserverclick="cmdSubmit2_Click" />
</form>
</body>
</html>
to submit a form with javascript is:
document.forms["myform"].submit();
but asp usually puts a whole bunch of javascript in the click for buttons to do with viewstate and things like that, so you might be better off adding a button that is set as the default for the form, and then hiding it with CSS.

ASP.NET TextBox OnTextChanged triggered twice in Firefox

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>
''''

ASP.Net Checkbox value at postback is wrong?

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>

Resources