Check what control initiated AJAX Request - asp.net

asp.net 2.0 / jQuery / AJAX
<script type="text/javascript">
//updated to show proper method signature
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(hideMessage);
function hideMessage(sender, args)
{
var ctl = args.get_postBackElement();
//check if ctl is the disired control
//hide user notification message
}
</script>
i have several controls on the page that might initiate the AJAX request, but i only want my js to fire when i click one particular button. how do i check what control initiated the request so i can fire JS accordingly.
EDIT: I worked around it, but I'd still like to know if I can do it this way.
Clarification: I can't call the JS from onclick event, because the page is inside of the UpdatePanel, and i only want the JS to execute when AJAX Request ends and it was triggered by one particular button on the page. On server side, i set the myLabel.Text to some text, and then js checks if the $(myLabel.CliendID)'s innerHTML is not blank and fires the js. checking the innerHTML is my work-around since i can't figure out how to check the "sender" of AJAX Request. Hope this makes more sense now.
edit2: I've read some documentation, and turns out you CAN check the "sender" control.
Thank you.

This is what I am doing in my code to identify what control has initialized the request. All javascript code.
function pageLoad() {
if (!Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack()) {
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequestHandler);
Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(initializeRequest);
}
}
function endRequestHandler(sender, args) {
if (sender._postBackSettings.sourceElement.id == '<%= gvResults.ClientID %>') {
//do something because of this...
}
}
function initializeRequest(sender, args) {
if (CheckForSessionTimeout()) {
args.set_cancel(true);
}
else {
if (sender._postBackSettings.sourceElement.id == '<%= gvResults.ClientID %>') {
//do something because of this
}
}
}
EDITHere is the method of checking for timeout on the client side.
var sessionTimeoutDateTime = new Date();
var sessionTimeoutInterval = <%= this.SesstionTimeoutMinutes %>;
function CheckForSessionTimeout() {
var currentDateTime = new Date()
var iMiliSeconds = (currentDateTime - sessionTimeoutDateTime);
if (iMiliSeconds >= sessionTimeoutInterval) {
ShowSessionTimeout();
return true;
}
return false;
}

I would recommend that you do not have each control execute the same javascript function. OR, if they do, pass a parameter that indicates which one executed it.
Then, you can include your ajax in the js function that the control executes.
And, if I'm not understanding the issue correctly, perhaps you could explain it in more detail or post some code.

I've read some documentation, and turns out you CAN check the "sender" control. JS in the question is updated to show the proper method signature.
This article gives even better explanation.

Related

Can't find ReportViewer event for rendering complete

I'm trying to fire an event (to remove a custom progress/status indicator) when the ReportViewer control is finished rendering. I've explored the events for the ReportViewer control and I can't seem to find one that actually fires when the report is complete.
I'm using Visual Studio 2010 and ASP.NET 4.
Thanks for your help.
I know this is old, but I wasn't satisfied with the polling approach. You can register a property change listener for changes to isLoading instead (as described here).
In summary, add a bit of javascript to the script manager e.g. in your form element:
<asp:ScriptManager ID="scriptManager" runat="server">
<Scripts>
<asp:ScriptReference Path="~/Reports/ReportViewer.js" />
</Scripts>
</asp:ScriptManager>
<rsweb:ReportViewer ID="reportViewer" runat="server"/>
Then hook it up and add any client-side logic you need in ReportViewer.js:
Sys.Application.add_load(function () {
$find("reportViewer").add_propertyChanged(viewerPropertyChanged);
});
function viewerPropertyChanged(sender, e) {
if (e.get_propertyName() == "isLoading") {
if ($find("reportViewer").get_isLoading()) {
// Do something when loading starts
}
else {
// Do something when loading stops
}
}
};
One option would be to continuously poll the isLoading property of the client side ReportViewer api. If the isLoading property returns true continue showing the progress indicator, if it returns false hide it and stop polling.
I haven't tried it myself but according to the documentation is look like it should work.
I achieve this using JQuery like so:
$(document).ready(function () {
document.getElementById('ctl00_ctl00_DefaultContent_AdminContent_reportViewer').ClientController.CustomOnReportLoaded = function () {
alert('You see this after Report is Generated');
}
});
Try below code snippet:
<script type="text/javascript">
var app = Sys.Application;
app.add_init(ApplicationInit);
function ApplicationInit(sender) {
var prm = Sys.WebForms.PageRequestManager.getInstance();
$('#ReportViewer1_ctl05').css('width', '1047px');
if (!prm.get_isInAsyncPostBack()) {
prm.add_endRequest(EndRequest)
}
}
function EndRequest(sender, args) {
var reportViewerControlId = "ReportViewer1";
if (sender._postBackControlClientIDs[0].indexOf(reportViewerControlId) >= 0) {
// do your stuff
}
}
</script>
EndRequest function will be triggered once report rendering gets completed.

ASP.NET AJAX Server Control - Detecting Instantiation of Control

I am creating a custom .NET AJAX Server Control, and need to get access to the JavaScript object functionality associated with that control. I can do this by finding the control in the ScriptManager using the $find method. However, I need to determine when I can call $find. If I do this on the "onload" event of the body of my HTML page, it can't find the control. Thus I end up having to locate the control with each event I wire up and my code ends up looking like this:
function button1_click() {
var control = $find("<%=Control.ClientID%>");
control.DoSomething();
}
function button2_click() {
var control = $find("<%=Control.ClientID%>");
control.DoSomethingElse();
}
I would rather store that control once, and use it throughout the rest of my event calls. Thus I'm hoping the code would eventually look something like this:
var _control = null;
function load() {
_control = $find("<%=Control.ClientID%>");
}
function button1_click() {
_control.DoSomething();
}
function button2_click() {
_control.DoSomethingElse();
}
Let me know if this doesn't make sense. I am new at creating these custom controls, so I'm not quite sure of the terminology yet. Thanks for your help!
The "load" DOM event occurs before the ASP.NET Ajax client-side framework is initialized. Client-side controls are initialized by handling the init event of the Sys.Application object. That's why an ASP.NET Ajax control's initialization script is output like:
Sys.Application.add_init(function() {
$create( ... )
});
You can use the load event of the Sys.Application object or its shortcut- the pageLoad method. It occurs after the init event and all ASP.NET Ajax controls will be initialized then. Here is some sample code:
var _control = null;
function pageLoad() {
_control = $find("<%= Control1.ClientID %>");
}

How to detect/track postback in javascript?

How to detect/track/check postback in javascript(e.g in asp.net Page.isPostBack())?
Any suggestion?
ASPX:
<input type="hidden" id="_ispostback" value="<%=Page.IsPostBack.ToString()%>" />
Client-side Script:
function isPostBack() { //function to check if page is a postback-ed one
return document.getElementById('_ispostback').value == 'True';
}
PS: I have not tested it but I've done somthing similar before and it works.
In some cases, you may want to check for postback without any server-side code. For example, in SharePoint, you cannot have code blocks in SharePoint Designer pages, so you can't use any solution that requires <%=something %>. Here is an alternative that involves no server-side code:
<script type="text/javascript">
function isPostBack()
{
return document.referrer.indexOf(document.location.href) > -1;
}
if (isPostBack()){
document.write('<span style="color:red;">Your search returned no results.</span><br/>');
}
</script>
One caveat (or feature, depending on how you look at it), this will detect not just postbacks, but any instance where the page links to itself.
If you want to check whether the current page will be a postback if the user clicks on a submit button, you can check for the presence of ViewState:
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="xxxxx" />
You can use something like document.getElementById("__VIEWSTATE") or the jQuery equivalent.
However, if you want to see whether the current page was generated in response to a postback, then you need to insert that data into the page on the server side first.
For example:
function isPostBack() {
return <%= Page.IsPostBack %>;
}
As JavaScript shouldn't be written with server-side code, and injecting new elements into the page seems like overkill, it seems to me that the simplest solution is to add [datat-*] attributes to the <head> element:
In Page_Load:
Page.Header.Attributes["data-is-postback"] IsPostBack ? "true" : "false";
This can then be accessed as:
jQuery:
$('head').data('isPostback');
Vanilla JS:
document.head.getAttribute('data-is-postback') === 'true';
Of course, if you treat the [data-is-postback] attribute as a boolean attribute, you could alternatively use:
In Page_Load:
if (IsPostBack)
{
Page.Header.Attributes.Add("data-is-postback", "");
}
else
{
Page.Header.Attributes.Remove("data-is-postback");
}
jQuery:
$('head').is('[data-is-postback]');
Vanilla JS:
document.head.hasAttribute('data-is-postback')
I have a solution that worked for me.
// Postback catch
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function (s, e) {
alert("post back");
});
See following:
<script type="text/javascript">
function invokeMeMaster() {
var chkPostBack = '<%= Page.IsPostBack ? "true" : "false" %>';
if (chkPostBack == 'false') {
alert('Only the first time');
}
}
window.onload = function() { invokeMeMaster(); };
</script>
You can only keep track of the postback if you are using AJAX requests or have a hidden field of some sort that the javascript reads on page load. Otherwise the page is regenerated and all POST data is lost; as you would expect and hope.
on Page_Load on your server-side :
The following uses an overload of RegisterClientScriptBlock() that will surround our string with the needed script tags
Server-Side
if (Page.IsPostBack){
ClientScript.RegisterClientScriptBlock(GetType(),
"IsPostBack", "var isPostBack = true;", true);
}
Then in your script which runs for the onLoad, check for the existence of that variable.
if (isPostBack){
//do something here
}
This should work for ASP.Net pages without relying on a backend supplied variable/control:
function isPostBack(frmID) {
var eventtarget = "";
var eventargument = "";
if (!!frmID) {
if (document.forms.length == 0) return false;
sForm = document.forms[0];
}
else {
sForm = document.getElementById(frmID);
if (!sForm) return false;
}
if (sForm.__EVENTTARGET) eventtarget = sForm.__EVENTTARGET.value;
else return false;
if (sForm.__EVENTARGUMENT) eventargument = sForm.__EVENTARGUMENT.value;
else return false;
if (eventtarget != "" || eventargument != "") return true;
else return false;
}
This is a simple JS way to determine the status of IsPostBack that I just got working in the Body of my ASPX page; needed to cause a PostBack during PageLoad for a project.
<script type="text/javascript">
if ('False' === '<%= Page.IsPostBack.ToString()%>')
{
__doPostBack();
}
</script>
Here is solution using jQuery:
$("a[href^='javascript:__doPostBack']").click(function () {
alert('ok');
});

How to call a client-side method from an asp.net method?

I have the following javascript:
<script type="text/javascript">
function showjQueryDialog() {
$("#dialog").dialog("open");
}
$(document).ready(function() {
$("#dialog").dialog({
autoOpen: false,
modal: true,
buttons: { "Renew Membership": function() { $(this).dialog("close"); } }
});
});
</script>
I have an asp:Button on the page which logs the user it. This is the sample of what I want to occur when the button is clicked on the server-side:
protected void LoginButton_OnClick(object sender, EventArgs e)
{
UserProfile profile = UserProfile.GetUserProfile(txtUserName.Text);
TimeSpan ts = profile.Expiration.Subtract(DateTime.Now);
if(ts.Days <= 30)
//call showJQueryDialog() to open the dialog box
Page.ClientScript.RegisterStartupScript(typeof(Login2), "showjquery",
"showJQueryDialog();", true);
else
//log the user in as normal.
}
Also is how would I attach a method such as the following to the Renew Button on the Dialog
public void Renew()
{
Response.Redirect("Renew.aspx");
}
As calling client side function is not possible I would suggest to emit in javascript the information required for the decision and make everything happen on the client side.
Alternatively you can do need a page reload, as suggested from previous commenter.
if(ts.Days <= 30)
ScriptManager.RegisterStartupScript(
typeof(MyPage), "showjquery",
"$(document).ready(function() { showJQueryDialog(); };",
true
)
else
//log the user in as normal.
Put that right where you have: //call showJQueryDialog() to open the dialog box
Update 1: You seem to be using an update panel, in that case you need to use ScriptManager.RegisterStartupScript
Update 2: You also want to wrap the js call in a jquery .ready call, so it isn't triggered before the dialog has been configured. This is better than hooking up the body onload because onload waits for images to be loaded so .ready will show sooner (depending on the images and other bits of info loaded).
I really don't understand Freddy's approach to this at all. I am misunderstanding something maybe. The way I see it, there are only two possibilities here, as devdimi point out. Either:
a) Do all the logic in the client-side onClick javascript. You could call an AJAX method that performs the action in the server-side OnClick, then call your jQuery popup in the AJAX callback.
b) Do a postback, handle the server-side OnClick, then attach javascript for the page that runs in the body onLoad event:
body.Attributes.Add("onLoad", "showJQueryDialog();")
I would keep a hidden LinkButton and then call the __doPostBack method in javascript.
<asp:LinkButton runat="server" ID="Renew" OnClick="Renew_Click" style="display:none" />
jQuery
$(document).ready(function() {
$("#dialog").dialog({
autoOpen: false,
modal: true,
buttons: { "Renew Membership": function() {
$(this).dialog("close");
__doPostBack('Renew', '');
// or if inside a master page something like this
__doPostBack('ctl00$ContentPlaceHolder1$Renew', '');
} }
});
});
I have a somewhat similar issue with IE8.
We're using ASP.NET and anytime we do a Response.Redirect within the PageLoad/Control-Events IE8 sets all the base DOM objects to undefined (Image, window, document)
But if we do the redirect during the PreInit event then IE8 is fine.. Lovely

JQuery ajaxStart event not being captured in ASP.net AJAX

I have an asp.net page with a save button within an updatepanel and contenttemplate. The save works nicely, but I am trying to add a "wait" gif while the save is happening using JQuery, but the ajaxStart event is not firing. I put a simple catch shown below:
$(document).ajaxStart(function () {
alert('starting');
}).ajaxStop(function () {
alert('done');
});
No alerts show when I click the save. Is there a problem when trying to capture ASP.net Ajax events, is asp doing some funky type of Ajax calls that can't be captured by Jquery?
Thanks, let me know if you have any ideas about this,
Mark.
The ASP.NET update panels seem to do their own thing... Tap into the PageReuqestManager and setup your own calls here...
EDIT
I simplified the functions a bit below to match your sample a little more...
<script type="text/javascript">
function pageLoad() {
if (!Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack()) {
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(AjaxEnd);
Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(AjaxBegin);
}
}
function AjaxEnd(sender, args) {
alert("I am done...");
}
function AjaxBegin(sender, args) {
alert("I am about to start...");
}
</script>

Resources