Setting hidden input value in Javascript, then accessing it in codebehind - c#

I have been trying to set the value of a hidden input by using Javascript and then access the value from within my C# codebehind. When I run the code that is copied below, the value that is assigned to assignedIDs is "", which I assume is the default value for a hidden input. If I manually set the value in the html tag, then assignedIDs is set to that value.
This behavior suggests to me that the value of the input is being reset (re-rendered?) between the onClientClick and onClick events firing.
I would appreciate any help with the matter. I have spent hours trying to solve what seems like a very simple problem.
html/javascript:
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Admin Page - Manage Tasks</title>
<script language="javascript" type="text/javascript">
function PopulateAssignedIDHiddenInput() {
var source = document.getElementById('assignedLinguistListBox');
var s = "";
var count = source.length;
for (var i = count - 1; i >= 0; i--) {
var item = source.options[i];
if (s == "") { s = source.options[i].value; }
else { s = s.concat(",",source.options[i].value); }
}
document.getElementById('assignedIDHiddenInput').Value = s;
// I have confirmed that, at this point, the value of
// the hidden input is set properly
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Panel id="EditMode" runat="server">
<table style="border: none;">
<tr>
<td>
<asp:Label ID="availableLinguistLabel" runat="server" Text="Available"></asp:Label><br />
<asp:ListBox ID="availableLinguistListBox" runat="server" Rows="10" SelectionMode="Multiple"></asp:ListBox>
</td>
<td>
<input type="button" name="right" value=">>"
onclick="Javascript:MoveItem('availableLinguistListBox', 'assignedLinguistListBox');" /><br /><br />
<input type="button" name="left" value="<<"
onclick="Javascript:MoveItem('assignedLinguistListBox', 'availableLinguistListBox');" />
</td>
<td>
<asp:Label ID="assignedLinguistLabel" runat="server" Text="Assigned To"></asp:Label><br />
<asp:ListBox ID="assignedLinguistListBox" runat="server" Rows="10" SelectionMode="Multiple"></asp:ListBox>
</td>
</tr>
</table>
//-snip-
<asp:Button ID="save_task_changes_button" runat="server" ToolTip="Click to save changes to task"
Text="Save Changes" OnClick="save_task_changes_button_click" OnClientClick="Javascript:PopulateAssignedIDHiddenInput()" />
</asp:Panel>
<!-- Hidden Inputs -->
<!-- Note that I have also tried setting runat="server" with no change -->
<input id="assignedIDHiddenInput" name="assignedIDHiddenInput" type="hidden" />
</div>
</form>
</body>
c#
protected void save_task_changes_button_click(object sender, EventArgs e)
{
string assignedIDs = Request.Form["assignedIDHiddenInput"];
// Here, assignedIDs == ""; also, Request.Params["assignedIDHiddenInput"] == ""
// -snip-
}

In javascript you need the value property to be lowercase, like this:
document.getElementById('assignedIDHiddenInput').value = s;
Then it will be set properly :) You can see an example in action here
Though if you alert the .Value it will show your value, you've actually added a new .Value property, but you haven't set the input's .value property which is what gets posted to the server. The example link above illustrates this both ways.
Also you can make it a bit faster especially if you have lots of options by using an array instead of string concatenation, like this:
var source = document.getElementById('assignedLinguistListBox');
var opts = [];
for (var i = 0; i < source.options.length; i++) {
opts.push(source.options[i].value);
}
var s = opts.join(',');
Edit: The above code is updated, CMS is right that the previous method was browser dependent, the above should now behave consistently. Also, if jQuery is an option, there are shorter ways of getting this info still, like this:
var s = $('#assignedLinguistListBox option').map(function() {
return this.value;
}).get().join(',');
$('#assignedIDHiddenInput').val(s);
You can see a working example of this here

I'm assuming ASP.NET here.
If so, your problem is the id of the control in the HTML generated by ASP.NET is not going to be "assignedIDHiddenInput" that you reference in the script. ASP.NET changes those before rendering the HTML from what you specify in the HTML page declaratively. Do a view source on the page and you will see what I mean.
Here is a way around that:
document.getElementById('<%=assignedIDHiddenInput.ClientID %>').value = s;
Update: As noted in the comments, this is only relevant if the control is set to RunAt=Server.

I think ASP.NET is calling the javascript to execute a postback on that control before your javascript function is called to populate that hidden value.
I think it's possible to disable the default postback and handle it yourself but I'm sure others can advise better.
Stick an alert() into your function there to see if it is really getting called before post-back is triggered.

Related

ASP checkbox 'checked' attribute always returning true

I have several asp:checkboxes on my webform which are filled in on page load, then returned on button submit.
the buttons are always returning the same as the server boolean behind them, no matter whether changed on the client side before being returned. After checking the clientID of the variables, they are exactly the same so it is not down to any hidden IDs or anything like that.
ASPX
<script type="text/javascript">
function slideTable(link) {
$(link).parent().next().toggle()
$(link).find(".navPlus").toggleClass("rotate1");
$(link).find(".navPlus").toggleClass("rotate");
var txt = $(link).parent().next().is(':visible') ? 'Minimise' : 'View all';
$(link).find(".navPlus").text(txt);
};
function boxchange(box) {
//Change has already happened at this point
if ($(box).prop("checked")==true) {
$(box).attr("checked", "checked");
}
else {
$(box).removeAttr("checked");
}
var table = $(box).closest('table');
var allChecked = $('#subjectsTable :checkbox:checked').length == $('#subjectsTable :checkbox').length;
if (allChecked) {
$(table).prev().find(":input").prop("checked", true);
$(table).prev().find(":input").attr("checked", true);
}
else {
$(table).prev().find(":input").prop("checked", false);
$(table).prev().find(":input").attr("checked", false);
}
};
</script>
<div>
<span class="headerSpan" onclick="slideTable(this)" style="clear:both" >
<img class="logo-image" alt="HalsburyLogo" src="../images/siteStyle/logo.png"/>
<span class="navPlus rotate1">View all</span>
</span>
<input onclick="chkHeader_click(this)" style="float:none; display:inline" type="checkbox" id="chkSubjects"/>
</div>
<table id="subjectsTable" class="subscriptionTable">
<tr>
<td style="width: 300px">
<label>Art</label></td>
<td>
<asp:CheckBox onclick="boxchange(this)" ID="chkArt" CssClass="chkSubject" runat="server" /></td>
</tr>
</table>
When a submit button is clicked, the value of chkArt is always the same. - upon checking, the clientID of chkArt on the serverside is also chkArt
edit: in the page load event the following code is present:
chkArt.Checked = //a bool from the database
chkArt.Checked = //a bool from the database
This code is in Page_Load? Unless you're conditionally running this code (which you aren't in the question at least...) then this is being executed every time the page loads. Page_Load is invoked whenever a request is made to a page, postback or otherwise.
So essentially your page is receiving the changed values, but ignoring them and just resetting them to their previous state.
You can conditionally check for postbacks in Page_Load:
if (!IsPostBack)
chkArt.Checked = //a bool from the database
That way the initial state of the CheckBox is set only on the initial load of the page, and not re-set on every postback.

ASP.NET AJAX UpdatePanel & Dynamic HTML Insertion Issue (Telerik)

Ok so I have a problem. I am currently working on a project using the Telerik framework for ASP.NET AJAX, although that shouldnt matter much as I am bypassing Telerik completely (almost) for this portion of the work.
I'm putting together a facebook-like chat program into our company's CRM system and, while all has gone well up to this point, I've hit a roadblock. The problem is when I try to "create a new chatbox". I'm using the asp control UpdatePanel in conjunction with a jQuery $.ajax call to pass a JSON method name to my code behind file. Here's the JSON logic:
DoubleClick on user in userlist:
$telerik.$(".UserListEntry").dblclick(function () {
var ToName = $telerik.$(this).children(".UserListEntryName").text();
var FromName = $telerik.$("#lkUserGeneralSettings").text();
$telerik.$.ajax({
type: 'POST',
url: 'DefaultHandler.ashx',
data: { "ToName": ToName, "FromName": FromName },
success: CreateChatBox(),
error: function (response) { alert("error: 001"); }
});
});
CreateChatBox callback:
function CreateChatBox() {
$telerik.$.ajax({
type: 'POST',
url: 'Default.aspx',
data: { MethodName: "CreateChatBox" },
success: ForceAsyncPostback,
error: function (response) { alert("error: 002"); }
});
}
Force asyncpostback (shouldn't be necessary, but this doesnt even work either!):
function ForceAsyncPostback() {
var UpdatePanel1 = '<%=Panel3.ClientID%>';
if (UpdatePanel1 != null) {
__doPostBack(UpdatePanel1, '');
}
alert("Success");
}
The UpdatePanel is created through various literals and some hard-coded html good-ole' fashioned divs. The problem is NOT with the dynamic creation of said elements, this works just fine. In fact my code behind (which I will post below) creates and displays everything perfectly fine if I place it into my PageLoad event.
At any rate, here's the .aspx:
<asp:UpdatePanel ID="Panel3" runat="server" OnLoad="Panel3_Load" UpdateMode="Conditional">
<ContentTemplate>
<asp:Literal ID="ChatBoxesLiteralTop" runat="server" />
<asp:Literal ID="ChatBoxesLiteralMid" runat="server" />
<asp:PlaceHolder ID="ChatBoxesPlaceHolder" runat="server" />
<asp:Literal ID="ChatBoxesLiteralBot" runat="server" />
<div id="UserListCorner">
<img id="UserListBtn" src="images/list.png" />
</div>
<div id="UserList" class="UserListHidden">
<div id="UserListView">
<asp:Literal ID="UserListViewLiteral" runat="server" />
</div>
</div>
</ContentTemplate>
</asp:UpdatePanel>
Code Behind:
protected void Panel3_Load(object sender, EventArgs e)
{
#region Ajax methods
if (Request.Form["MethodName"] == "CreateChatBox")
{
CreateChatBox();
}
#endregion
Engine m_engine = new Engine();
string m_sql = #"SELECT FullName FROM Users WHERE RecordDeleted <> 1";
DataTable dt = m_engine.GetObjectsAsDataTable(m_sql);
for (int i = 0; i < dt.Rows.Count; i++)
{
UserListViewLiteral.Text += "<div class='UserListEntry'><span class='UserListEntryStatus'><img src='images/status-online.png' width='10' /></span> <span class='UserListEntryName'>" + dt.Rows[i]["FullName"].ToString() + "</span></div>";
}
RadAjaxManager.GetCurrent(Page).ResponseScripts.Add("ChatAjax()");
}
private void CreateChatBox()
{
ChatBoxesLiteralTop.Text = #"<div id='ChatBox' class='ChatBoxHidden'>
<div class='ChatBoxHeader'>
<img id='ChatBoxStatusBtn' src='Images/status-online.png' />
<span id='ChatBoxUserLabel'>John Doe</span>
<img id='closeBtn' src='Images/close.png' />
<img id='toggleTab' src='Images/up-arrow.png' />
</div>
<div id='ChatBoxMessageOutput'></div><div class='ChatBoxFooter'>";
TextBox txt = new TextBox();
txt.ID = "ChatBoxMessageInput";
txt.Height = 16;
txt.MaxLength = 270;
txt.Width = 250;
txt.AutoPostBack = false;
ChatBoxesPlaceHolder.Controls.Add(txt);
RadButton btn = new RadButton();
btn.ID = "ChatBoxSendButton";
btn.Text = "Send";
btn.AutoPostBack = true;
btn.Height = 22;
btn.Click += ChatBoxSendButton_Click;
ChatBoxesPlaceHolder.Controls.Add(btn);
ChatBoxesLiteralBot.Text = "</div></div>";
Panel3.Update();
RadAjaxManager.GetCurrent(Page).ResponseScripts.Add("ChatAjax()");
}
I'm certainly overlooking something outrageously stupid, but a fresh set of eyes from a seasoned ASP.Net Ajaxer would be really appreciated! Thanks in advance.
Clarification of Issue
What DOES work:
The code runs properly.
The JSON method is passed to the code behind and read.
The CreateChatBox() method runs through and allegedly populates the literals and controls.
All callbacks in the JSON chain are executed successfully.
What DOES NOT work:
The UpdatePanel, even after the redundant postback, does not have
this new HTML after code executes successfully.
To Whom It May Concern
Well I happened to solve this problem the day after posting it. Of course there are now new hurdles to tackle but I am happy to say that my asynchronous chat module is nearly done. Since nobody decided to take on the problem, I am going to post what I did to properly produce dynamic, asynchronous objects based on hard-coded HTML in ASP.NET since, while Googling the matter, this post was the only relevant result popping up.
I'll start by saying I am well aware that this is a very unconventional approach. That being said, the requirements of the project justified the means. While there may be many other ways to accomplish your goal, this does work. I am not going to go into extraneous details with respect to my particular project, but hopefully this will help somebody in the future.
The Wrongs
The primary problem with my original question was the way I was attacking the rendering sequence. A major flaw in my logic was attempting to separate the ASP controls (literals, placeholders, buttons and such) from my HTML too much. My initial approach (from above) looked like this:
<asp:UpdatePanel ID="Panel3" runat="server" OnLoad="Panel3_Load" UpdateMode="Conditional">
<ContentTemplate>
<asp:Literal ID="ChatBoxesLiteralTop" runat="server" />
<asp:Literal ID="ChatBoxesLiteralMid" runat="server" />
<asp:PlaceHolder ID="ChatBoxesPlaceHolder" runat="server" />
<asp:Literal ID="ChatBoxesLiteralBot" runat="server" />
<div id="UserListCorner">
<img id="UserListBtn" src="images/list.png" />
</div>
<div id="UserList" class="UserListHidden">
<div id="UserListView">
<asp:Literal ID="UserListViewLiteral" runat="server" />
</div>
</div>
</ContentTemplate>
</asp:UpdatePanel>
The final result looks more like this:
<asp:UpdatePanel ID="Panel3" runat="server" OnLoad="Panel3_Load" UpdateMode="Conditional">
<ContentTemplate>
<asp:PlaceHolder ID="ChatBoxesPlaceHolder" runat="server" />
<div id="UserListCorner">
<img id="UserListBtn" src="images/list.png" />
</div>
<div id="UserList" class="UserListHidden">
<div id="UserListView">
<asp:Literal ID="UserListViewLiteral" runat="server" />
</div>
</div>
<asp:Label ID="Label42" Font-Bold="true" runat="server" />
<asp:HiddenField runat="server" ID="LatestDisplayTick" />
</ContentTemplate>
</asp:UpdatePanel>
With the code behind (abridged) similar to this:
Literal top = new Literal();
// ...
UpdatePanel UpdatePanel2 = new UpdatePanel();
// ...
top.Text = #"<div id='ChatBox' class='ChatBoxShown'>
<div class='ChatBoxHeader'>
<img id='ChatBoxStatusBtn' src='Images/status-online.png' />
<span id='ChatBoxUserLabel'>" + UserNames[0] + #"</span>
<img id='closeBtn' src='Images/close.png' />
<img id='toggleTab' src='Images/up-arrow.png' />
</div>";
top.ID = "ChatBoxesLiteralTop";
top.Mode = LiteralMode.PassThrough;
// ...
UpdatePanel2.ID = "UpdatePanel2";
UpdatePanel2.UpdateMode = UpdatePanelUpdateMode.Conditional;
UpdatePanel2.ChildrenAsTriggers = false;
UpdatePanel2.ContentTemplateContainer.Controls.Add(top2);
// ...
Panel3.ContentTemplateContainer.Controls.Add(top);
Panel3.ContentTemplateContainer.Controls.Add(UpdatePanel2);
Panel3.ContentTemplateContainer.Controls.Add(mid);
What It Means
All I've done is wrapped the entirety of my chatbox elements inside a single placeholder, dynamically creating HTML elements that wrap ASP controls all from the server and posting it as a "chunk" of dynamic data. This sidesteps some strange behaviors with ASP control placement otherwise, and allows for a quasi-OO approach for the client-side functionality of my project. After creation, I can now make use of some JSON and AJAX calls to dynamically enter data into said dynamically created controls.
An example would be posting a message received from a database notification to my chat window (ChatBoxesLiteralMid control) when it is received.
After Page/Control Load
if(ChatBoxesLiteralMid != null)
ChatBoxesLiteralMid.Text += #"<div class='ChatBoxEntry'><span class='ChatBoxEntryName ChatBoxSelf'>" + AppParameters.Current.AppUser.FirstName + "</span>: <span class='ChatBoxEntryMessage'>" + dy.Rows[dy.Rows.Count - 1]["Message"].ToString() + "</span></div>";
Why Go To The Trouble?
What I have accomplished is for a particular project with needs to go far above and beyond the original scope, started by another developer years prior. This is an unconventional way to teach the old dog some new tricks. I now have near-full control of an indiscriminate amount of real-time chat boxes/sessions on the CLIENT side. It's really pretty freakin' sweet honestly. Please feel free to post questions (or concerns) as I regularly check SO and am happy to respond.

Return lat and long values of user's current location to be used in a sql query

I am using HTML5 geolocation to obtain a users current location & display this on a google map. However I also want to return the lat and long values of this location and pass these values to a SQL datasource query. I want a lat variable and and a long variable to pass through. To get the lat I am simply assigning var jsVar = position.coords.latitude but this is not returning anything. I realise that I should be using hiddenfields to achieve to send the var to the server but am not totally sure how exactly to do it when there is more than one hiddenfield. Any help would be really appreciated. Here is what I have:
Javascript
function SetHiddenVariable() {
var jsVar = position.coords.latitude;
// Set the value of the hidden variable to
// the value of the javascript variable
var hiddenControl = '<%= inpHide.ClientID %>';
document.getElementById(hiddenControl).value = "Latitude = " + jsVar;
}
ASP.NET
<body onload="SetHiddenVariable()">
<form id="form1" runat="server">
<div>
<input id="inpHide" type="hidden" runat="server" />
<asp:TextBox ID="txtJSValue" runat="server"></asp:TextBox>
<asp:Button ID="btnJSValue"
Text="Click to retrieve Javascript Variable"
runat="server" onclick="btnJSValue_Click"/>
</div>
</form>
</body>
Code Behind C#
protected void btnJSValue_Click(object sender, EventArgs e)
{
txtJSValue.Text = inpHide.Value;
}
you could just concatinate the data on the client side (use a comma or some other delimiter that makes sense to you and then just separate on the server side. You would only need to use one variable in that case.
Here is the html way of doing this which should get you started. You'll just need to wire your button click event and turn the inputs into server side controls. Good luck!
<!DOCTYPE html>
<html>
<head>
<script>
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(success);
}
function success(position) {
document.getElementById("lat").value = position.coords.latitude;
document.getElementById("long").value = position.coords.longitude;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
Lat: <input id="lat" type="text" />
Long: <input id="long" type="text" />
</div>
</form>
</body>
</html>

Select All Checkbox feature in gridview not being implemented

I am having header in gridview that labels as "xls" and a checkbox, that when selected should select all the checkbox columns in gridview and unchecking the xls column should uncheck all the columns.
I am following two links:
Link-1
Here, the totalChkBoxes variable is coming null (despite my gridview has rows). In fact when debugging the JS, code inside parseInt and below line is coming as ''
Link-2
Here also the GridView2 variable is coming null.
One common change that i am doing in both the JS is replacing the <%=.....%> by <%#....%>
Please guide as to what i am doing wrong. You can also help by giving some suitable link to implement the desired functionality
CODE UPDATED WITH MY WORKING JS
<script type="text/javascript" language="javascript">
function checkAllBoxes() {
var gvControl = document.getElementById("gvSample");
//this is the checkbox in the item template.
var gvChkBoxControl = "chkSelectItem";
//Header Template checkbox.
var mainChkBox = document.getElementById("chkBoxAll");
//Array of Inputs in gridview.
var inputTypes = gvControl.getElementsByTagName("input");
for (var i = 0; i < inputTypes.length; i++) {
//if the input type is a checkbox and the id of it is what we set above
//then check or uncheck according to the main checkbox in the header template
if (inputTypes[i].type == 'checkbox' && inputTypes[i].id.indexOf(gvChkBoxControl, 0) >= 0)
inputTypes[i].checked = mainChkBox.checked;
}
}
GRIDVIEW CODE
<asp:TemplateField>
<HeaderTemplate>
<table style="width: 15px" cellpadding="0" cellspacing="0">
<tr>
<td>
<asp:Label ID="lblXls" runat="server" Text="xls"></asp:Label>
<br />
<input id="chkBoxAll" type="checkbox" onclick="checkAllBoxes()" />
</td>
</tr>
</table>
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="chkSelectItem" runat="server" />
</ItemTemplate>
</asp:TemplateField>
Thanks!
Try changing your parseInt to something like this to see if it helps at all. I know it's only a small change, but small things tend to break JS code:
var totalChkBoxes = parseInt("<%=gvTest.Rows.Count%>");
Secondly, if you have runat="server" on the checkbox in the header, you may need to change this line if your JSFunction:
var mainChkBox = document.getElementById("<%=chkBoxAll.UniqueID%>");

How to access a Div inside a repeater using javascript

Simply, I have an anchor inside a repeater that triggers on click a javascript function, which sets the innerHTML of a Div to some content.
trying this outside a repeater did work!
but if I tried to implement the same code in the repeater's item template, it won't work!
NOTE: I think I need to access the repeater first then access the Anchor inside it! but I don't know how to do it
For further illustration:
JavaScript Function:
function show(ele, content) {
var srcElement = document.getElementById(ele);
if (srcElement != null) {
srcElement.innerHTML = content;
}
}
The repeater's code:
<asp:Repeater ID="Repeater1" runat="server" >
<ItemTemplate>
Name : <%# Eval("name")%>
<DIV ID= "PersonalInfo1" runat="server"></DIV>
<A id="A1" href="#" runat="server" onclick="show('PersonalInfo1','Address : ')">More...</A>
</ItemTemplate>
</asp:Repeater>
PS: THE POSTED CODE ISN'T WORKING IN THE REPEATER!
That is because id's are unique. Select elements using getElementsByName or by their class name with for example jQuery.
OK... let's start over.
Have such repeater code:
<asp:Repeater ID="Repeater1" runat="server" >
<ItemTemplate>
<div>
Name : <%# Eval("name")%>
<div id="Address" runat="server" style="display: none;"><%# Eval("address")%></div>
<div id="Interests" runat="server" style="display: none;"><%# Eval("interests")%></div>
<a id="A1" href="#" runat="server" onclick="return show(this, 'Address');">Show address</a>
<a id="A2" href="#" runat="server" onclick="return show(this, 'Interests');">Show interests</a>
</div>
</ItemTemplate>
</asp:Repeater>
Then such JavaScript code:
function show(oLink, targetDivID) {
var arrDIVs = oLink.parentNode.getElementsByTagName("div");
for (var i = 0; i < arrDIVs.length; i++) {
var oCurDiv = arrDIVs[i];
if (oCurDiv.id.indexOf(targetDivID) >= 0) {
var blnHidden = (oCurDiv.style.display == "none");
oCurDiv.style.display = (blnHidden) ? "block" : "none";
//oLink.innerHTML = (blnHidden) ? "Less..." : "More...";
}
}
return false;
}
This will search for "brother" DIV element of the clicked link, and show or hide it.
The code is as simple as possible using pure JavaScript, you should be able to understand what each line is doing - feel free to ask if you don't. :)
Note, you have to put the personal info in the PersonalInfo div in advance instead of passing it to the function - the function will get pointer to the clicked link.
Yes you need to iterate all the relevant links. Solution that involve minimal change of code is adding class to the links then check for this class:
<A id="A1" href="#" runat="server" class="RepeaterLink" ...>
And then in JavaScript:
var arrLinks = document.getElementsByTagName("a");
for (var i = 0; i < arrLinks.length; i++) {
var oLink = arrLinks[i];
if (oLink.className == "RepeaterLink") {
//found link inside repeater..
oLink.click();
}
}
This will "auto click" all the links, you can check ID or something else to imitate click of specific link in the repeater as well.

Categories