PDA

View Full Version : [FIXED] [V0.7] Button Disabled



Timothy
Oct 30, 2008, 2:46 PM
Hello,

The following example used to work, for some reason over the past couple revisions it has stopped working. I'm not sure if this is by design, or it was working because it was originally a bug. Please advise.

Example.aspx:


<%@ 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">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="True" />
<ext:ScriptManager ID="ScriptManager2" runat="server" StateProvider="PostBack" />
<ext:TabPanel ID="TabPanel1" runat="server" AutoPostBack="True" AutoHeight="True" DeferredRender="True">
<Tabs>
<ext:Tab ID="Tab1" runat="server" Title="Tab 1">
<Body>
<ext:ComboBox ID="ComboBox1"
runat="server">
<Listeners>
<Select Handler="#{Button1}.enable();" />
</Listeners>
<Items>
<ext:ListItem Text="Example" Value="Example" />
</Items>
</ext:ComboBox>
<ext:Button ID="Button1" runat="server" Text="Button 1" Disabled="True" />
</Body>
</ext:Tab>
<ext:Tab ID="Tab2" runat="server" Title="Tab 2">
<Body>
Tab 2 Content
</Body>
</ext:Tab>
</Tabs>
</ext:TabPanel>
</form>
</body>
</html>


Replication steps:

1. Load page
2. Notice Button1 is disabled
3. Select "Example" from ComboBox1
4. Notice Button2 is enabled
5. Click Tab2
6. Click Tab1
7. Notice Button1 is disabled again?

As mentioned earlier, Button1 used to be enabled in step #7. Any suggestions would be much appreciated.

Hope this makes sense.

Cheers,
Timothy

geoffrey.mcgill
Oct 31, 2008, 12:20 PM
Hi Timothy,

Are you positive this scenario was working before? The issue is that you're making a client-side change the state of the <ext:Button>, but not persisting that change across postbacks.

The TabPanel is set to DeferredRender, which when switching Tabs will cause the TabPanel to be completely rebuilt using server-side code and ViewState.

Any client-side changes are not persisted on a PostBack.

I think you should be able to persist the Buttons Enabled/Disabled state during a TabChange by moving the <Select> Listener to a <Select> AjaxEvent and ensure the ViewStateMode is set to "Include".


<AjaxEvents>
<Select OnEvent="ComboBox1_Select" ViewStateMode="Include" />
</AjaxEvents>

Hope this helps.

Timothy
Oct 31, 2008, 12:26 PM
Hello Geoffrey,

Thanks for the response, I'm 99% sure it worked before, but to make it easy on you this weekend I'm going to move back to a revision I have on my white board that was proven, just as a sanity check ;)

Will get back to you with my results and will post here.

Cheers,
Timothy

geoffrey.mcgill
Oct 31, 2008, 12:36 PM
Thanks for the update. 

If you get this exact same code sample working with an earlier build, certainly let us know. Unfortunately I just don't think this scenario is going to work (it should not work) without somehow persisting the Buttons state change. A couple options to persist the change include using a <Select> AjaxEvent, or maybe pushing a boolean flag value into a Hidden <input> field which you reconstitute on PostBack. 


Anywho, let us know what you uncover. 

Timothy
Nov 02, 2008, 3:26 PM
Geoffrey,

You were right, the example I provided above would not work, and I understand from your explanation why. I think in trying to simplify my example I may have confused the problem, if you take a look at my revised example below, it would appear to be a problem with the Listeners of the GridPanel SelectionModel.

OK, explanation; in rev 670 when you highlight a customer, and click the Edit button from the tool bar, you will be switched to Tab 2. If you click Tab 1 again, the Edit button is still active because the Listener is re initiated again. However, as of rev 688 (SVN current) this functionality has gone away.

An additional issue from the example below, works in IE6 and not FF3.0, unrelated to the original issue reported, perhaps one of you can help me out with why FF3.0 can not resolve #{btnEdit} in the RowSelect handler?

Example.aspx:


<%@ Page Language="C#" %>
<%@ Register Assembly="Coolite.Ext.Web" Namespace="Coolite.Ext.Web" TagPrefix="ext" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
Customers.DataSource = new object[] {
new object[] { "1", "Timothy" },
new object[] { "2", "Geoffrey" }
};
Customers.DataBind();
}
protected void btnEdit_Click(object sender, EventArgs e)
{
TabPanel1.SetActiveTab(Tab2);
}
</script>
<!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">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="True" />
<ext:ScriptManager ID="ScriptManager2" runat="server" StateProvider="PostBack" />
<ext:Store ID="Customers" runat="server" AutoLoad="True">
<Reader>
<ext:ArrayReader ReaderID="CustomerId">
<Fields>
<ext:RecordField Name="CustomerId" Type="Auto" />
<ext:RecordField Name="Customer" />
</Fields>
</ext:ArrayReader>
</Reader>
<SortInfo Field="Customer" Direction="ASC" />
</ext:Store>
<ext:TabPanel ID="TabPanel1" runat="server" AutoPostBack="True" DeferredRender="True">
<Tabs>
<ext:Tab ID="Tab1" runat="server" AutoHeight="True" Title="Tab 1">
<Body>
<ext:FitLayout runat="server">
<ext:GridPanel ID="dgSearchResults"
runat="server"
StoreID="Customers"
AutoExpandColumn="Customer"
AutoHeight="True"
AutoWidth="True"
ButtonAlign="Right"
Stateful="True"
StripeRows="True">
<TopBar>
<ext:Toolbar runat="server">
<Items>
<ext:ToolbarFill runat="server" />
<ext:ToolbarButton ID="btnEdit" runat="server" AutoPostBack="True" &#111;nclick="btnEdit_Click" Disabled="True" StandOut="True" Text="Edit" MinWidth="80" />
</Items>
</ext:Toolbar>
</TopBar>
<ColumnModel>
<Columns>
<ext:RowNumbererColumn />
<ext:Column ColumnID="Customer" Header="Customer" DataIndex="Customer" Hideable="False" Sortable="True" />
</Columns>
</ColumnModel>
<SelectionModel>
<ext:RowSelectionModel ID="SearchResultSelection" runat="server" SingleSelect="True">
<Listeners>
<RowSelect Handler="#{btnEdit}.enable()" />
<RowDeselect Handler="#{btnEdit}.disable()" />
</Listeners>
</ext:RowSelectionModel>
</SelectionModel>
</ext:GridPanel>
</ext:FitLayout>
</Body>
</ext:Tab>
<ext:Tab ID="Tab2" runat="server" AutoHeight="True" Title="Tab 2">
<Body>
Word
</Body>
</ext:Tab>
</Tabs>
</ext:TabPanel>
</form>
</body>
</html>


Cheers,
Timothy

Timothy
Nov 03, 2008, 11:39 AM
Geoffrey,

Does the above make sense? Let me know if it requires further explanation.

Cheers,
Timothy

geoffrey.mcgill
Nov 03, 2008, 2:12 PM
Hi Timothy,

I apologize for the delay in confirming a fix for this defect. It ended up being a difficult problem to solve.

The fix has been committed to SVN.

Now the problem still exists that if you "enable" the Button with JavaScript and do a postback, the enabled/disabled state of the Button will not persist.

As mentioned above, there are several options to work around this issue, some client-side and others server-side.

Another couple options that I investigated is checking for Selected Rows during the postback and just toggleing the enabled/disabled state if some rows are selected.

Another option would be adding an <Activate> Listener to "Tab1". The following example demonstrates.

Example


<ext:Tab ID="Tab1" runat="server" AutoHeight="True" Title="Tab 1">
...
<Listeners>
<Activate Handler="new Ext.util.DelayedTask(function() {
if(!Ext.isEmpty(#{SearchResultSelection}.getSelect ed())) {
#{btnEdit}.enable();
}}).delay(200);" />
</Listeners>
</ext:Tab>

The Activate event fires very early in the Tabs client-side lifecycle, and well before the GridPanel or Toolbar have been instantiated. Because of this, the "btnEdit" object is not available during the <Activate> event. To work-around the issue I had to wrap the .getSelected() check in a DelayedTask in order to buy a bit of time to allow the GridPanel+Toolbar+Button to instantiate themselves.

When you get a chance to SVN update and test the new code, please confirm if things are working well now and I'll mark this defect as [FIXED].

Hope this helps.

Timothy
Nov 03, 2008, 3:11 PM
Hmm, can you make a function for the SelectionModel similar to the ComboBox FireSelectOnLoad which will fire the RowSelect Listeners of the SelectionModel on load?

Would be proper brilliant.

Cheers,
Timothy

Vladimir
Nov 03, 2008, 3:15 PM
Hi Timothy,

The GridPanel has SilentSelectionInit property (Set init selecetion without event fires). Default value is true. So, you can set it to false for fire RowSelect event.

Timothy
Nov 03, 2008, 3:21 PM
Sounds promising vlad,

However, doesn't work with the following example:

Example.aspx:


<%@ Page Language="C#" %>
<%@ Register Assembly="Coolite.Ext.Web" Namespace="Coolite.Ext.Web" TagPrefix="ext" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
Customers.DataSource = new object[] {
new object[] { "1", "Timothy" },
new object[] { "2", "Geoffrey" }
};
Customers.DataBind();
}
protected void btnEdit_Click(object sender, EventArgs e)
{
TabPanel1.SetActiveTab(Tab2);
}
</script>
<!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">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="True" />
<ext:ScriptManager ID="ScriptManager2" runat="server" StateProvider="PostBack" />
<ext:Store ID="Customers" runat="server" AutoLoad="True">
<Reader>
<ext:ArrayReader ReaderID="CustomerId">
<Fields>
<ext:RecordField Name="CustomerId" Type="Auto" />
<ext:RecordField Name="Customer" />
</Fields>
</ext:ArrayReader>
</Reader>
<SortInfo Field="Customer" Direction="ASC" />
</ext:Store>
<ext:TabPanel ID="TabPanel1" runat="server" AutoPostBack="True" DeferredRender="True">
<Tabs>
<ext:Tab ID="Tab1" runat="server" AutoHeight="True" Title="Tab 1">
<Body>
<ext:FitLayout runat="server">
<ext:GridPanel ID="dgSearchResults"
runat="server"
StoreID="Customers"
AutoExpandColumn="Customer"
AutoHeight="True"
AutoWidth="True"
ButtonAlign="Right"
Stateful="True"
SilentSelectOnInit="False"
StripeRows="True">
<TopBar>
<ext:Toolbar runat="server">
<Items>
<ext:ToolbarFill runat="server" />
<ext:ToolbarButton ID="btnEdit" runat="server" AutoPostBack="True" &#111;nclick="btnEdit_Click" Disabled="True" StandOut="True" Text="Edit" MinWidth="80" />
</Items>
</ext:Toolbar>
</TopBar>
<ColumnModel>
<Columns>
<ext:RowNumbererColumn />
<ext:Column ColumnID="Customer" Header="Customer" DataIndex="Customer" Hideable="False" Sortable="True" />
</Columns>
</ColumnModel>
<SelectionModel>
<ext:RowSelectionModel ID="SearchResultSelection" runat="server" SingleSelect="True">
<Listeners>
<RowSelect Handler="#{btnEdit}.enable()" />
<RowDeselect Handler="#{btnEdit}.enable()" />
</Listeners>
</ext:RowSelectionModel>
</SelectionModel>
</ext:GridPanel>
</ext:FitLayout>
</Body>
</ext:Tab>
<ext:Tab ID="Tab2" runat="server" AutoHeight="True" Title="Tab 2">
<Body>
Word
</Body>
</ext:Tab>
</Tabs>
</ext:TabPanel>
</form>
</body>
</html>


Cheers,
Timothy

Vladimir
Nov 03, 2008, 11:11 PM
Hi Timothy,

I have fixed code.

Please note that I renamed SilentSelectionInit to FireSelectOnLoad
Now default value of GridPanel FireSelectOnLoad is false. You can set it to true to fire RowSelect event on page load.

Please, let me know if you still have problems with it

Thank you

Timothy
Nov 03, 2008, 11:38 PM
Cheers vlad, I will check it in the morning ;)

Timothy

Timothy
Nov 04, 2008, 10:36 AM
Confirmed resolved.

Cheers,
Timothy