Monday, March 26, 2012

Trigger a panel refresh from javascript/pure html control

Hi,

I have a pure HTML tree control, that is outside of an ajax UpdatePanel. I want to write a JS function that triggers a particular panel to refresh, *as if* I hit a submit button inside of the panel. I don't want to put the HTML tree control inside an Ajax panel, as it will loose it's state (it will return to a completely collapsed state).

Putting a button inside the panel, and then running the JSelement.click() event from my tree control works in IE, but Firefox submits the entire page(the submit event is not captured by the AJAX framework in FF in this case,apparently).

I have looked into the client reference documentation at http://ajax.asp.net/docs/ClientReference/Global/default.aspx, and it seems like there should be a way to trigger a postback/panel refresh, but I have not found a way.

The PageRequestManager does not help, since it only monitors existing page requests. I need to invoke a page request, and run something like

PageRequest.Invoke('MyUpdatePanel');

or

var ajaxpanel = document.getElementById('AjaxPanelClientID');
ajaxpanel.update();

A related suggestion:

It would be nice if the UpdatePanel supported client side triggers, not just server side triggers. Consider the following hypothetical code:

<ajax:UpdatePanel ID="ajxUpdatePanel2" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<!-- CONTENT -->
</ContentTemplate>
<Triggers >
<ajax:AsyncPostBackTrigger ClientTriggerFunction="MyCustomTrigger" OnTrigger="MyCustomTrigger_ontrigger" />
</Triggers>
</ajax:UpdatePanel>

Then the system would automatically generate the JS function (with the appropriate .NET ajax framework calls that I don't need to know about), so I can call it anywhere on the page, from multiple HTML controls if needed.

<input type="button" value="MyHTMLButton" onclick="MyCustomTrigger('argstring');">

The system should enable a code-behind event handler where I can put my server side code:

protected void MyCustomTrigger_ontrigger(object sender, AjaxClientTriggerEventArgs e) {
//run some server side .NET code here
switch(e.ClientArgString){
...
}
}


You can trigger an asynchronous post back by invoking the __doPostBack function. Just pass in the ID of the control that's either inside an update panel or is marked as a trigger for one. Here's an example:

<asp:UpdatePanel ID="up" runat="server">
<ContentTemplate>
<asp:Button ID="myButton" runat="server" OnClick="myButton_Click" Text="Click me!" />
<asp:Label ID="myLabel" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
<input id="myOtherButton" type="button" value="No, click me!" />
<script type="text/javascript">
function pageLoad() {
$addHandler($get('myOtherButton'), 'click', triggerAsyncPostBack);
}
function triggerAsyncPostBack(e) {
__doPostBack('<%= myButton.UniqueID%>', '');
}
</script>

One thing to watch out for is that the first parameter to __doPostBack needs to be the full ID of the control. If you're using master pages, your control IDs will be longer than they appear. Use the UniqueID property to get the full ID or the event handlers for your control won't run on the server.

Also, if you have event validation turned on (the default), you'll get an exception if you don't pass in a correct event argument as the second parameter to __doPostBack. For button controls, it should be the empty string. For other controls, it might be different, but you'll have to experiment to find out.

Hope this helps.


Thank you Jason,

That is the behaviour I was looking for, and it works in Firefox as well as IE. I knew about the _doPostBack function in general, but I did not know the syntax to call it.

Where is the best place to find documentation and syntax for the built-in ASP.NET and AJAX JS functions and calls? For example, I did not know about $get or $addHandler functions.

(I am familiar with similar functions from the prototype.js library).

Thanks again :-)


Another related discovery that is slightly more elegant (I am probably repeating what some already know...but I think its great :-)

Is is not necessary to use a button to trigger the post back inside the panel. I updated a hidden input field with a value, and then submitted thehidden field iteself with __doPostBack, and it worked great. I needed a hidden field to pass in a unique ID anyway, so the panel would know how to refresh itself.

Inside the UpdatePanel:

<input id="txtGroupID" type="hidden" runat="server" onserverchange="txtGroupID_ServerChange" />

JS code:

txt = $get("<%=this.txtGroupID.ClientID %>");
txt.value = somevalue;
__doPostBack("<%=this.txtMatGroupID.UniqueID %>","");



Douglas Smith:

Where is the best place to find documentation and syntax for the built-in ASP.NET and AJAX JS functions and calls? For example, I did not know about $get or $addHandler functions.

The ASP.NET AJAX documentation does document all of these functions. You'd have to know where to look, though. All of the $-prefixed functions seem to be documented in the Sys.UI namespace here:

http://ajax.asp.net/docs/ClientReference/Sys.UI/default.aspx

Browsing through the source code helps find the undocumented stuff.


That will trigger an asynchronous post back, but no event will be raised on the server with that control as the target. You probably want to execute some code to modify the controls inside the update panel or there'd be little point in triggering the asynchronous post back. That's why I used a button control in the example I gave you. If all you want to do is trigger the asynchronous post back and don't care about raising a specific event on the server, you could use the ID of the update panel control as the event target. To me, that would be stating the intention of what you're trying to do a little clearer.

If you don't want to use a button but do want to raise an event on the server, you can use any control that implements IPostBackEventHandler as the event target. Those controls have a RaisePostBackEvent method that gets invoked when a post back is received with their ID as the event target. For button controls, they raise their Click event in that method. That's where your code gets to do its stuff. You could easily create an "empty" custom control that didn't render anything, but could be used as the event target. (I tried using the page control for this, but there's code that prevents you from registering the page as an asynchronous post back trigger.)

It'd be nice if the UpdatePanel control itself implemented IPostBackEventHandler and raised some sort of custom event on the server that let you do this without having to write much custom code. You could simulate this a bit by putting some code inside one of the event handlers on your page and checking to see if the ScriptManager control's AsyncPostBackSourceElementID is the ID of the UpdatePanel control you used as the event target. If so, execute your custom code.

Hope this helps.

No comments:

Post a Comment