jQuery's $() function always returns 'undefined' with AJAX - asp.net

i've noticed that popup shows BEFORE text gets updated in the textbox, i guess js gets called before the page gets rendered ... that would explain the 'undefined' popup ... how do i make sure js gets called AFTER the page is rendered?
rewriting to make it as simple as possible:
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:TextBox ID="txtRcaNotes" runat="server" TextMode="MultiLine" Width="800px"></asp:TextBox><br />
<asp:Button ID="btnDoneWithRcs" runat="server" OnClick="btnDoneWithRcs_Click" Text="Action Completed / Update Notes" />
</ContentTemplate>
</asp:UpdatePanel>
</form>
<script type="text/javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(
function(){doStuff();}
);
function doStuff()
{
$(document).ready(function() {
$('txtRcaNotes').hide();
alert($('txtRcaNotes').attr('id'));
});
}
</script>
</body>
Code Behind:
protected void btnDoneWithRcs_Click(object sender, EventArgs e)
{
txtRcaNotes.Text += "asdfadf";
}
TEXTBOX DOESN'T GET HIDDEN, ALERT() RETURNS 'UNDEFINED'

You're just missing your id selector syntax. Try:
$('#<%= txtRcaNotes.ClientID %>').hide();
alert($('#<%= txtRcaNotes.ClientID %>').attr('id'));
Note the addition "#" prepended before each selector.

One thing you could try is using Firebug, or some other DOM inspector and check the actual element IDs that are being generated by ASP.NET before and after your AJAX call and see if they are the same.

Related

ASP.NET UpdatePanel - inline variable

I have a server-side variable which is assigned a value in PreRender. For the sake of simplicity, let's imagine I'm doing this:
protected string test;
protected void Page_PreRender(object sender, EventArgs e)
{
test = Guid.NewGuid().ToString();
}
In my markup, the variable is then referred to within an UpdatePanel, like so:
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Button ID="Button1" runat="server" Text="Perform postback" />
<script type="text/javascript">
Sys.Application.add_load(function () {
alert('<%=test%>');
});
</script>
</ContentTemplate>
</asp:UpdatePanel>
On first load of the page, the JavaScript alert function gives me a random value, as expected. However, on any subsequent postback, the original value of the Guid is retained.
Can anybody explain why this is so, and offer a solution? I'm fairly sure I can achieve the required behaviour by putting the value of 'test' in a hidden field, for example, but ideally I wouldn't have to sink to those depths. Unfortunately replacing the UpdatePanel with something lighter isn't really an option.
I've found a solution to this, and nor is it quite as dirty as I'd feared. I declare a JS variable outside of the function:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Button ID="Button1" runat="server" Text="Perform postback" />
<script type="text/javascript">
var test;
Sys.Application.add_load(function () {
alert(test);
});
</script>
</ContentTemplate>
</asp:UpdatePanel>
In my code-behind, I assign the JS variable a value in the Sys.Application.add_init method, like so:
protected void Page_PreRender(object sender, EventArgs e)
{
ScriptManager.RegisterStartupScript(this, typeof(UpdatePanelTest), "startupScripts", "Sys.Application.add_init(function() {test='" + Guid.NewGuid().ToString() + "';});", true);
}
VoilĂ , a different Guid is then displayed on first load and every postback.

why ajax loader image always shown using jquery and asp.net

with asp.net code below my ajax_loader image doesn't work well and always shown ..
<asp:ScriptManager ID="MainScriptManager" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Label runat="server" ID="lblname">
Name</asp:Label><br />
<asp:TextBox runat="server" ID="txbname"></asp:TextBox><br />
<asp:Label ID="lblemail" runat="server">
Email</asp:Label><br />
<asp:TextBox runat="server" ID="txbemail" /><br />
<asp:Label runat="server" ID="lblsugg">
Suggestion</asp:Label><br />
<asp:TextBox runat="server" Rows="3" Columns="20" ID="txbsugg" TextMode="MultiLine"></asp:TextBox>
<asp:Button runat="server" ID="btnsubmit" OnClick="btnsubmit_onclick" Text="submit" />
<asp:Label runat="server" ID="lblresultmsg"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
<div id="loading">
<p>
<img src="Images/ajax-loader.gif" />
Please Wait</p>
</div>
and jquery code
$("#loading").ajaxStart(function() {
$(this).show();
}).ajaxStop(function() {
$(this).hide();
});
any suggestions !?
ajaxStart and ajaxStop works only for ajax request sent by jQuery, if you use other libraries or UpdatePanel, it won't help you.
jQuery only.
Whenever an Ajax request is about to be sent {With jQuery-gdoron}, jQuery checks whether there are any other outstanding Ajax requests. If none are in progress, jQuery triggers the ajaxStart event. Any and all handlers that have been registered with the .ajaxStart() method are executed at this time.
Example of jQuery ajax request that will fire the ajaxStart and ajaxStop:
$.ajax({
url: 'foo',
...
...
});
You could create a generic way to handle this by adding the following code to a common js include. Here's a quick and dirty example:
Note: Be sure you initialize it by calling SetupGlobalAjaxHandlers on your page load.
function SetupGlobalAjaxHandlers()
{
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
}
function InitializeRequest(sender, args)
{
if(typeof(OnPageInitRequest) != "undefined")
OnPageInitRequest();
}
function EndRequest(sender, args)
{
if(typeof(OnPageEndRequest) != "undefined")
OnPageEndRequest();
}
Then, in any page that includes the js file, you could optionally implement the OnPageInitiRequest() and OnPageEndRequest() methods. There, you could show/hide your loading indicator.
I do recommend, though, that you use an UpdateProgress control as you get the show/hide logic for free.
This technique opens up some possibilities for you, say, if you wanted to disable controls while a partial postback is occurring.

UI dialog problem with scriptManger and updatePanel

i call my UI dialog from page which has scriptManager, this way:
function openDialog() {
var $dialog = jQuery('#dialog');
$dialog.load('dialog.aspx');
$dialog.dialog({
autoOpen: false,
title: 'Add New Contact Personel',
modal: true,
height: 200,
width: 400,
show: 'puff',
hide: 'puff',
close: function (event, ui) {
$dialog.html('');
$dialog.dialog('destroy');
}
});
$dialog.dialog('open');
}
body of dialog.aspx looks like this:
<body>
<form id="form1" runat="server">
<%-- <asp:ScriptManagerProxy ID="proxyScriptor" runat="server"></asp:ScriptManagerProxy>
<asp:UpdatePanel ID="upadatePanel" runat="server" UpdateMode="Conditional">
<ContentTemplate>--%>
<div>
<table border="0">
<tr>
<th>SomeText:</th>
<th><asp:TextBox ID="someTextBox" runat="server"></asp:TextBox></th>
</tr>
</table>
</div>
<asp:Panel ID="updatePanel" runat="server">
<asp:Button ID="UpdateLoger" runat="server" Text="Update" onclick="Update_Click" />
</asp:Panel>
<%-- </ContentTemplate>
</asp:UpdatePanel>--%>
</form>
</body>
now: if i click updateBtn i want to update text in postback, close UI dialog and do refresh like this:
UpdateText(someTextBox.Text);
string script = #"jQuery('#dialog').html('');jQuery('#dialog').dialog('destroy');window.location.reload()";
ScriptManager.RegisterClientScriptBlock(this, typeof(UpdatePanel), "jscript", script, true);
so if add another script manager on this page for UI dialog, very very wird things have happend (like __doPostBack doesn't work), if i remove scriptManager, updatePanel doesnt show it contents, if i put scriptMangerProxy , updatePanel doesn't show it contents either. So how i should do it?
You've got a lot going on here. One problem you're running into is that you're treating dialog.aspx like it's loading into it's own window or iframe. In reality, its just being inserted as a document fragment into the page's DOM. I suspect if you inspect the source, you'll find multiple <body> tags.
There's several ways of doing this. My dialogs are typically unique to a particular page, so I'll handle the dialog somewhat like this:
Page.aspx
<html>
<head>...</head>
<body>
<!-- page content -->
<asp:Button ID="btnOpenDialog" runat="server" OnClick="btnOpenDialogClick" Text="Open Dialog" />
<asp:UpdatePanel ID="upDialogs" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Panel ID="pnlDialog" runat="server" CssClass="pnlDialog" Visible="false">
<!-- Dialog form -->
<asp:Button ID="btnSubmit" runat="server" OnClick="btnSubmitClick" Text="Submit" />
</asp:Panel>
</ContentTemplate>
<Triggers>
<asp:AsyncPostbackTrigger ControlID="btnOpenDialog" />
</Triggers>
</asp:UpdatePanel>
<script>
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function() {
$("div.pnlDialog").dialog({
autoOpen: true,
title: 'Add New Contact Personel',
modal: true,
height: 200,
width: 400,
show: 'puff',
hide: 'puff',
close: function (event, ui) {
$dialog.html('');
$dialog.dialog('destroy');
}
});
}
</script>
</body>
</html>
Page.aspx.cs
...
protected void btnOpenDialogClick(object sender, EventArgs e)
{
pnlDialog.Visible = true;
upDialogs.Update();
}
protected void btnSubmitClick(object sender, EventArgs e)
{
... save values ...
pnlDialog.Visible = false;
upDialogs.Update();
}
...
Basically, we register a JS function to fire every time the page performs an asynchronous postback. This functions looks for the dialog box code. If it finds it, it wires it up with jQueryUI. If it doesn't find anything, it just finishes silently. If you have multiple dialogs on the page, this can easily be refactored to flexibly handle them.

JQuery BlockUI with UpdatePanel Viewstate Issue

I have an update panel within a div that I modal using the JQuery plugin BlockUI. Inside the UpdatePanel is a textbox and a button. When I enter something in the textbox and click the button I am unable to retrieve the text in the textbox. When I debug it shows the textbox having no value.
<asp:UpdatePanel ID="upTest" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<div id="divTest">
<asp:TextBox ID="txtTestVS" runat="server" /><br />
<asp:Button ID="cmdTest" Text="TEST" OnClick="cmdTest_Click" UseSubmitBehavior="false" runat="server" />
</div>
</ContentTemplate>
</asp:UpdatePanel>
SERVER-SIDE:
protected void cmdTest_Click(object sender, EventArgs e)
{
string x = txtTestVS.Text;
}
This should clarify things. Here are the total contents of the page.
SHOW MODAL
<div id="divTest">
<asp:UpdatePanel ID="upTest" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:TextBox ID="txtTestVS" runat="server" /><br />
<asp:Button ID="cmdTest" Text="TEST" OnClick="cmdTest_Click" UseSubmitBehavior="false" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
</div>
This is a common problem with dialog plug-ins. The problem is when content is put in the blockUI container, it's appended to the element, and no longer in the form being submitted to the server. To solve this you need to edit the blockUI code a bit:
Here's the source: http://github.com/malsup/blockui/blob/master/jquery.blockUI.js
Change this:
Line 262:
var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el);
to:
var layers = [lyr1,lyr2,lyr3], $par = full ? $('form') : $(el);
and this:
Line 382:
els = $('body').children().filter('.blockUI').add('body > .blockUI');
to:
els = $('form').children().filter('.blockUI').add('form > .blockUI');
That should get you going and the textbox values coming through.
(Response courtesy of Nick Craver https://stackoverflow.com/users/13249/nick-craver)
If you are trying to use blockUI on a button within an update panel (i.e. you click the button within the update panel and the UI gets blocked), you need to handle it using PageRequestManager events
prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_beginRequest(function() {
$.blockUI({ message: '<img src="../../Content/images/Busy2.gif" />' });
});
prm.add_endRequest(function() {
$.unblockUI();
});
Or on a button click, if you want to display a modal window with this text box and a button, you can try something like this

ASP.NET 3.5: Display UpdateProgress during Page_Load()

I am building an ASP.NET site using Visual Studio 2008 and have a page looking like this (stuff snipped)
<asp:Content ID="Content2" ContentPlaceHolderID="PageContentPlaceHolder" runat="server">
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
the page here..
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdateProgress ID="UpdateProgress1" runat="server" DisplayAfter="100">
<ProgressTemplate>
<div>
<asp:Image ID="AjaxImage" runat="server" ImageUrl="Ajax.gif" />
</div>
</ProgressTemplate>
</asp:UpdateProgress>
</asp:Content>
The page_load starts a long (>5s) process
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
LongRunningProcess();
}
}
How can I display the UpdateProgress while the LongRunningProcess is running? It does work when I move the LongRunningProcess() call to a button onclick handler.
Move your page_load code into a new function.
Add a AJAX timer into the ContentTemplate section of your page. Set the interval to 500. (1/2 second)
Double-click on the Timer object in Design view to create a _tick handler.
In the _tick handler created in the previous step, call the following code
protected void My_Timer_Tick(object sender, EventArgs e)
{
My_Timer_Name.Enabled = false;
My_Page_Load_Function(); // Function created in step 1 above)
}
protected void My_Page_Load_Function()
{
System.Threading.Thread.Sleep(5000); // A delay to simulate doing something.
lblMyLabel.Text = "Done!"; // Write output to page.
}
Create a normal div that shows the Ajax.gif so it shows "processing" by default.
In the javascript pageLoad() function, make a call back to the page using Ajax's PageMethods.
function pageLoad(sender, args) {
PageMethods.getVersions(LoadVersionsCallback);
}
The method you are calling in your .aspx.cs file has to be static, it can take parameters and looks something like:
[System.Web.Services.WebMethod]
public static string getVersions()
{
StringBuilder sb = new StringBuilder();
... etc.
return sb.ToString();
}
The javascript function that you specified when you called the method will run when the method completes. It will be passed the results. At the end of this function you hide the Ajax.gif div.
function LoadVersionsCallback(result) {
// do something with the results - I load a dropdown list box.
...etc.
// here is where you hide your div holding the Ajax.gif
}
And then you work on making whatever it is you are doing run in less than 1 second....
I would put a Ajax timer on the page and set it for less than a second... It will only run once and after its first tick then you need to disable it otherwise it will fire again. (you don't want to start your long running process more than once...)
then on the OnTimerTick event I would start your long running process that way your page fully renders and you can display your UpdateProgress while its running.
you out to be able to move the code that you had for your button click to the time tick...
I used JBrooks idea above (i.e. showing the progress indicator as part of a Panel that also includes the Iframe, so that it shows even before the Iframe first loads), but simplified it: style the iframe so that when it does appear it is on top of the animated GIF.
Requires no Javascript or C# code-behind.
Here's the relevant ASPX, followed by the CSS. You'll have to noodle with the "top" setting in the style to cover the image you use.
<asp:Panel ID="DetailPanel" runat="server" CssClass="submitBox detailPanel">
<asp:Table ID="Table1" runat="server" Width="100%">
<asp:TableHeaderRow ID="TableHeaderRow10" runat="server">
<asp:TableCell ID="TableHeaderCell" runat="server"
Font-Bold="true" HorizontalAlign="Center">
Title Text
</asp:TableCell>
</asp:TableHeaderRow>
<asp:TableRow>
<asp:TableCell HorizontalAlign="Center">
<asp:Image ID="Image1" runat="server" ImageUrl="~/Images/animated_progress.gif" />
</asp:TableCell>
</asp:TableRow>
</asp:Table>
<div class="iframeOverlay">
<iframe id="IframeDetail" runat="server" style="width: 100%; height: 100%;" />
</div>
</asp:Panel>
.iframeOverlay
{
z-index: 2;
position: relative;
top: -50px;
}
With Jquery.
<script>
$(document).ready(function() {
$('#<%= UpdateProgress1.ClientID %>').show();
});
</script>
<script> $(document).ready(function() { $('#<%=
UpdateProgress1.ClientID %>').show(); }); </script>
This worked well for me, just had to add it to the end of the BODY section and works like a charm.

Resources