PDA

View Full Version : [INVALID] asp:UpdatePanel and ext:Window



haltenberg
Jun 10, 2008, 1:42 AM
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Button ID="Button1" runat="server" Text="Show window" />
<ext:Window ID="Window1" runat="server" Icon="Application"
Title="Title" Show&#111;nload="False" TriggerElement="Button1" Modal="True">
<Content>
<asp:Button ID="Button2" runat="server" Text="Click me" />
</Content>
</ext:Window>
</ContentTemplate>
</asp:UpdatePanel>

Click on a button inside ext:Window, which is in turn located in asp:UpdatePanel causes a full page postback. Is this normal or is it a bug?

PS. Is there any quick and easy way to implement something similar to asp.net ajax toolkit's ConfirmButton/ModalPopup extender, but with Coolite? Thanks!

geoffrey.mcgill
Jun 10, 2008, 5:36 AM
Hi haltenberg,

This full postback issue was brought up (http://forums.ext.net/showthread.php?postid=539.aspx) by someone yesterday and we have reproduced the issue.

The problem is caused because the dom/html elements are moved around with JavaScript after the page loads and moved outside of the UpdatePanel's . I think only the ViewPort and Window controls are affected. We're still thinking about how to fix the issue, although I'm sure it's possible.

The following sample demonstrates something similar to the ConfirmButton/ModalPopup Extender.

http://sandbox.ext.net/Window/ConfirmButton.aspx

Of course, you also have access to the complete Ext.MessageBox (http://extjs.com/deploy/dev/examples/message-box/msg-box.html) class... if you want to try and hand roll some functionality.

Hope this helps.

haltenberg
Jun 10, 2008, 4:07 PM
Geoffrey,

There is another problem with Coolite and asp:UpdatePanel:
As per your suggestion (http://forums.ext.net/showthread.php?threadid=553-5-1.aspx), I decided to give a try to Ext.MessageBox directly and tried to call Ext.MessageBox.confirm. However, when the triggering button in inside asp:UpdatePanel, nothing happens :-( No errors or anything, but also no reaction. As soon as I move the button outside of UpdatePanel, things work. I don't see any workarounds for now due to my page architecture: asp:UpdatePanel -> ext:Panel -> ext:BorderLayout -> ... my controls here.

geoffrey.mcgill
Jun 10, 2008, 4:10 PM
You're going to have to post some code for us to debug this.

haltenberg
Jun 10, 2008, 5:38 PM
I started creating sample code from my app and it turns out that the issue has nothing to do with asp:UpdatePanel... or maybe it does... As I have said, the triggering button resides inside ext:Panel, which in its turn is inside UpdatePanel. The source of the problem is that the ext:Panel is hidden on initial page load and displayed only during certain circumstances, and that is when things don't work as expected.

aspx:


<%@ Page Language="vb" AutoEventWireup="false" EnableEventValidation="false" CodeBehind="Default.aspx.vb" Inherits="TestWebApplication._Default" %>
<%@ Register Assembly="Coolite.Ext.Web" Namespace="Coolite.Ext.Web" TagPrefix="ext" %>
<%@ Register assembly="AjaxControlToolkit" namespace="AjaxControlToolkit" tagprefix="cc1" %>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server" />
<body>
<form id="form1" runat="server">
<ext:ScriptManager ID="ScriptManager1" runat="server" />
<asp:ScriptManager ID="ScriptManager2" runat="server" />
<script type="text/javascript">
Ext.onReady(function(){
Ext.get('btnDelete').on('click', function(e){
Ext.MessageBox.confirm('Confirm', 'Are you sure you want to delete this?', showResult);
});


function showResult(btn){
return(btn);
};
});
</script>


<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Button ID="btnShowPanel" Text="Show panel" runat="server" />
<ext:Panel ID="Panel1" runat="server" Height="350">
<Content>
<ext:BorderLayout ID="BorderLayout1" runat="server">
<Center>
<ext:TabPanel ID="Tabpanel1" runat="server" ActiveTab="0" Height="350" Plain="false">
<Tabs>
<ext:Tab ID="Tab1" runat="server" Title="Tab1"></ext:Tab>
<ext:Tab ID="Tab2" runat="server" Title="Tab2"></ext:Tab>
</Tabs>
</ext:TabPanel>
</Center>
<East>
<ext:Panel ID="Panel2" runat="server" Width="175" Title="Actions">
<Content>
<ext:Button ID="btnDelete" runat="server" Text="Delete" AutoPostBack="false"></ext:Button>
</Content>
</ext:Panel>
</East>
</ext:BorderLayout>
</Content>
</ext:Panel>
</ContentTemplate>
</asp:UpdatePanel>

</form>
</body>
</html>


codebehind:


Partial Public Class _Default
Inherits System.Web.UI.Page


Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Panel1.Hide()
End Sub


Protected Sub btnShowPanel_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnShowPanel.Click
Panel1.Show()
End Sub
End Class


When the page is loaded, only "Show panel" button is visible. When clicked, ext:Panel is displayed. Clicks on "Delete" button do not bring the confirm Messagebox. Thus the problem appers to be with panel hiding/unhiding. Any clues on how to make it work?

Thanks!

geoffrey.mcgill
Jun 10, 2008, 7:50 PM
Hi haltenberg,

When any Control (Coolite or otherwise) inside an UpdatePanel gets reloaded (after async PostBack), any client-side JavaScript events which were attached during the previous (or initial) page_load are removed and must be re-added.

Just remember that when stuff inside an UpdatePanel gets reloaded/rerendered after a async postback, it's like it never existed before. Any client-side events that you manually added will have to be recreated. This is not a problem specific to Coolite, although we provide plenty of ways to work around this "feature".

Specifically, you have the line which begins "Ext.get('btnDelete')". That event is added on inital Page_Load. After a async postback, the event will not be re-attached to "btnDelete" because nothing is triggering your original onReady block to fire again.

If you plan on using the UpdatePanel, then I would recommend either attaching the Listeners from code-behind, or adding inline to the <Listeners>.

Example


<ext:Button ID="btnDelete" runat="server" Text="Delete" AutoPostBack="false">
<Listeners>
<Click Handler="Ext.MessageBox.confirm('Confirm', 'Are you sure you want to delete this?');" />
</Listeners>
</ext:Button>

I also just recently posted a page to the sandbox demonstrating several techniques for attaching Listeners, see http://forums.ext.net/showthread.php?postid=574.aspx.

As well, I'm assuming that you're doing some backend processing to determine if the Panel needs to be show/hide, but if not, you do not require a postback in order to show/hide the Panel. You could just attach a simple JavaScript 'click' event to the button and call Panel1.hide(); from JavaScript.

Example


Panel1.hide();
or,
Panel1.show();

Hope this helps.

haltenberg
Jun 10, 2008, 10:48 PM
Geoffrey,

Many thanks for all the information and the hint how to get the confirmBox from button's handler! This approach works like a charm.

I thought that the page goes through the whole lifecycle during asynch postback. I am not loading any controls dynamically (only hiding/unhiding the panel), hence expected all events to recreate themselves... I assume the issue is with Ext.onReady not running in asynch postback?

Indeed, there is back-end logic to decide whether to display the panel or not... Actually, that is one of the reasons I use UpdatePanel.

As for the Ext.MessageBox.confirm: if the button has AutoPostBack="false", then the event never reaches the server, no matter which button was clicked (Ok/Cancel). If I turn AutoPostBack to "true", postback occurs immediately with the display of the confirmation box. Isn't it supposed to be the same way like in ASP.Net:


<asp:Button ID="btn" runat="server" Text="Delete" OnClientClick="return confirm('Are you sure?');" />

or am I just missing something?

Thank you!

geoffrey.mcgill
Jun 10, 2008, 11:09 PM
I thought that the page goes through the whole lifecycle during asynch postback. I am not loading any controls dynamically (only hiding/unhiding the panel), hence expected all events to recreate themselves... I assume the issue is with Ext.onReady not running in asynch postback?
The whole page does go through the entire lifecycle during an async postback, but your onReady script is not inside the UpdatePanel and will not get executed when the contents of the UpdatePanel are re-rendered. I think placing your onReady script block inside the UpdatePanel might work, although in this case I would still suggest adding the Listeners inline or from code-behind.

Here's some ExtJS documentation that might help explain the capabilities of the MessageBox...

"Note that the MessageBox is asynchronous. Unlike a regular JavaScript <code>alert</code> (which will halt
browser execution), showing a MessageBox will not cause the code to stop." Direct Link to Documentation (http://extjs.com/deploy/dev/docs/?class=Ext.MessageBox)

If all you are doing is showing/hiding the Panel, it does not need to be contained within an UpdatePanel.

Example


<%@ Page Language="C#" %>

<%@ Register
Assembly="Coolite.Ext.Web"
Namespace="Coolite.Ext.Web"
TagPrefix="ext"
%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
protected void ShowButton_Click(object sender, EventArgs e)
{
this.Panel1.Show();
}

protected void HideButton_Click(object sender, EventArgs e)
{
this.Panel1.Hide();
}
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server" />
<body>
<p><a href="TabPanel.aspx">Reload</a></p>
<form id="form1" runat="server">
<ext:ScriptManager ID="ScriptManager1" runat="server" />
<asp:ScriptManager ID="ScriptManager2" runat="server" />

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="ShowButton" />
<asp:AsyncPostBackTrigger ControlID="HideButton" />
</Triggers>
</asp:UpdatePanel>

<asp:Button
ID="ShowButton"
runat="server"
Text="Show"
&#111;nclick="ShowButton_Click"
/>

<asp:Button
ID="HideButton"
runat="server"
Text="Hide"
&#111;nclick="HideButton_Click"
/>

<ext:Panel ID="Panel1" runat="server" Title="My Panel" Height="300">
<Content>
Other Controls Here...
</Content>
</ext:Panel>

</form>
</body>
</html>

haltenberg
Jun 11, 2008, 1:41 PM
Geoffrey,

Thank you for the explanations about MessageBox being asynchronous. I guess I will need to disable autopostback and use a callback function to decide whether to make a postback or not.


geoffrey.mcgill (6/10/2008)If all you are doing is showing/hiding the Panel, it does not need to be contained within an UpdatePanel.

Unfortunately, it's a bit trickier than just show/hide. I have an update panel with a gridview in it. Depending on selected gridview row, I show the details in a Tabpanel. If no row is selected, or gridview is paged/sorted, I am hiding the tabpanel.