This is a migrated thread and some comments may be shown as answers.

Cancel Ajax request from usercontrol

9 Answers 230 Views
Ajax
This is a migrated thread and some comments may be shown as answers.
Justin Lee
Top achievements
Rank 1
Justin Lee asked on 20 May 2010, 07:34 PM
I have multiple RadGrids on a page, each in a separate usercontrol.  Each have Export functionality, and the export buttons are in RadMenus.  The page has a RadAjaxManager, and each usercontrol has a RadAjaxManagerProxy.  Since RadAjaxManagerProxy's do not have an OnRequestStart method, I handle the cancel of the ajax request on the main page.

Code to handle 1 of the usercontrols:
        function PageAjaxRequestStart(sender, args) {  
            if (args.EventTarget == '<%= ctrlGrid1.menu1.UniqueID %>') {  
                var menu = $find('<%= ctrlGrid1.menu1.ClientID %>');  
                var index = menu._findItemByValue('EXPORT').get_index().toString();  
                if (args.EventArgument.match("^"+index) == index) {  
                    args.set_enableAjax(false);  
                }  
            }  
        } 

This works fine, but I'm wondering if there is a better way to do it...  To make this solution work, I have to expose the menu in each usercontrol publicly, and the page has to know about the exporting feature of the usercontrol. (any page that the usercontrol is added to would have to implement this solution).  It would be nice if there was some way to handle this from within the usercontrols.  Please let me know if there is a better way.

Thanks 

9 Answers, 1 is accepted

Sort by
0
Accepted
Veli
Telerik team
answered on 25 May 2010, 12:29 PM
Hello Justin,

You can find the RadAjaxManager instance in the content page from the user control. You can then register a client-side OnRequestStart event handler, the javascript handler of which will be in the user control. The following code can be executed from the Page_Load method of the user control:

RadAjaxManager.GetCurrent(Page).ClientEvents.OnRequestStart = "ajaxRequestStart";

Now, the definition of ajaxRequestStart can go into your web control markup inside a RadScriptBlock:

<telerik:RadScriptBlock ID="RadScriptBlock1" runat="server">
    <script type="text/javascript">
        function ajaxRequestStart(sender, args)
        {
            if (args.get_eventTarget().indexOf("ExportTo") > -1)
            {
                args.set_enableAjax(false);
            }
        }
    </script>
</telerik:RadScriptBlock>

That's it. you are registering an event handler for the manager right from the user control. No need to take the code for disabling AJAX on export outside of the user control where it is relevant.

Note, however, a few limitations to this approach.

1. You are overriding the client-side OnRequestStart event handler definition for the AJAX manager. RadAjaxManager.ClientEvents.OnRequestStart accepts a single name of a javascript function. You are accessing the manager from the user control and setting the property. This means that if the content page or another user control also wanted to use this event, only the last set function would be executed. This property can specify only a single event handler and only one party can claim  the event handler in this way.

2. If you have multiple user controls on the same page, they would all register their own ajaxRequestStart function. This would mean multiple definitions of a javascript function with the same name on page, which means always the last defined function will be executed. Not the behavior you may want.

To alleviate both of these limitations of the given approach, a safer, more robust approach can be used. We can set a master javascript function as the OnAjaxRequest event handler of the manager. Each user control or another party that wants to use the OnRequestStart event can then specify an event handler that will be called by the master handler.

So, supposing the following RadAjaxManager definition and event handler:

<telerik:RadAjaxManager ID="RadAjaxManager1" runat="server">
    <ClientEvents OnRequestStart="OnAjaxRequestStart" />
</telerik:RadAjaxManager>
 
<script type="text/javascript">
    function OnAjaxRequestStart(sender, args)
    {
        for (var i = 0; i < OnAjaxRequestStart.handlers.length; i++)
        {
            OnAjaxRequestStart.handlers[i](sender, args);
        }
    }
 
    OnAjaxRequestStart.handlers = [];
</script>

You can see I have expanded the OnAjaxRequestStart function with an array that will hold references to the actual event handler that I want executed. The function itself simply iterates over these handlers and calls them.

Now, what I have in the user control is a startup script that will push a function into OnAjaxRequestStart.handlers which will be executed on AJAX request:

protected void Page_Load(object sender, EventArgs e)
{
    ScriptManager.RegisterStartupScript(Page,
        typeof(Page),
        "disableAjaxOnExport_" + this.UniqueID,
        String.Format(@"
            OnAjaxRequestStart.handlers.push(function(sender, args){{
                var target = args.get_eventTarget();
                if (target.indexOf('{0}') > -1 && target.indexOf('ExportTo') > -1){{
                    args.set_enableAjax(false);
                }}
            }});", RadGrid1.UniqueID),
        true);
}

The above is the Page_Load method of the user control. Each user control I place on the page registers its own event handler by adding a reference to the function into the handlers array. When an AJAX request is triggered, OnAjaxRequestStart calls all the event handlers in the array.

Sample page and user control is attached.

Best wishes,
Veli
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Justin Lee
Top achievements
Rank 1
answered on 26 May 2010, 10:19 PM
Perfect. This is what I was looking for. (the second part) Thank you.
0
Erin
Top achievements
Rank 1
answered on 30 Jul 2012, 03:12 PM
I am using almost identical ScriptManager.RegisterStartupScript code in the Page_Load of one of my pages, and I added an alert(OnAjaxRequestStart.handlers); just to make sure everything was being attached correctly (the page has several user controls and instances of RadAjaxManagerProxy, so wires get crossed with Ajax sometimes).  This showed that the handler was being added correctly on Page_Load, but was being added again after every asynchronous Ajax postback.  Whenever I would click a RadButton, the alert would appear again with OnAjaxRequestStart.handlers containing another copy of the function disabling Ajax for the specified button.

This seems like a problem, since OnAjaxRequestStart.handlers surely has some kind of limits on its capacity, and at the very least it seems like running through potentially hundreds of event handlers could slow the page down.

I considered placing the ScriptManager.RegisterStartupScript code inside if(!Page.IsPostBack), but then the handlers get cleared when a full postback occurs, which won't work for my project (Ajax still needs to be disabled on the button after a full postback).  What would ideally happen is that the function should only be added to OnAjaxRequestStart.handlers on Page_Load if it is not an Ajax postback, but I don't know if that is possible from the server side.

Thank you!    
0
Maria Ilieva
Telerik team
answered on 02 Aug 2012, 10:44 AM
Hi Erin,

Note that it is more correct to attach the handler on each request as in most cases the code in the OnRequestStart function will be executed conditionally. However you could try to check if the ScriptManager IsInAsyncPostBack :
RadScriptManager.GetCurrent(Page).IsInAsyncPostBack()


All the best,
Maria Ilieva
the Telerik team
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.
0
Nicolaï
Top achievements
Rank 2
answered on 02 May 2013, 08:19 AM
..Or just wrap the user control in a radajaxpanel, and set the ClientEvents-OnRequestStart..?
Can even call the same function name without conflicts.
0
Joseph
Top achievements
Rank 1
answered on 05 May 2015, 12:03 AM

I have a very similar situation to the original poster, and trying the solution works up to the point of registering the function for OnRequestStart.

I put the RadAjaxManager.GetCurrent(this.Page).ClientEvents.OnRequestStart = ajaxRequestStart; in the page load of my user control, and the function is in a RadScriptBlock on the user control mark up. However when loading the main page I get a javascript error "Uncaught ReferenceError: ajaxRequestStart is not defined". This makes me think that the page load is trying to register the function before the javascript is rendered to the page, so it can't see it. The various controls are in separate radpageviews.

0
Maria Ilieva
Telerik team
answered on 07 May 2015, 09:59 AM
Hi Joseph,

Try to call the "ajaxRequestStart" function with some TimeOut and see if this makes any difference.


Regards,
Maria Ilieva
Telerik
 

See What's Next in App Development. Register for TelerikNEXT.

 
0
Joseph
Top achievements
Rank 1
answered on 07 May 2015, 09:17 PM
I was using a separate button from the ones built into the grid to export. I was able to get it working by putting "RadAjaxManager.GetCurrent(this.Page).ClientEvents.OnRequestStart = ajaxRequestStart; " in the page prerender event and explicitly ajaxifying the button in the radajaxmangerproxy. 
0
Maria Ilieva
Telerik team
answered on 12 May 2015, 08:02 AM
Hi Joseph,

 I'm glad that you were able to fix the issue on your end. Do not hesitate to contact us back if further assistance is needed.

Regards,
Maria Ilieva
Telerik
 

See What's Next in App Development. Register for TelerikNEXT.

 
Tags
Ajax
Asked by
Justin Lee
Top achievements
Rank 1
Answers by
Veli
Telerik team
Justin Lee
Top achievements
Rank 1
Erin
Top achievements
Rank 1
Maria Ilieva
Telerik team
Nicolaï
Top achievements
Rank 2
Joseph
Top achievements
Rank 1
Share this question
or