PDA

View Full Version : [CLOSED] DirectEvent does not populate Combobox after DirectEvent Parent Refresh.



michaeld
Jan 17, 2014, 11:41 AM
To reproduce the issue, click the trigger pulldown for State. This will cause SelState DirectEvent to populate the State ComboBox. So far so Good.
Now select California. This will call the DirectMethod ReRender the Parent FieldContainer.
Now click the trigger pulldown for County. This is where it breaks. Even though the Response populates correctly, the pulldown does not populate with the new entries.



<%@ Page Language="C#" EnableViewState="false" ClassName="Test44" %>

<script runat="server">
protected void Page_Load( object sender, EventArgs e ) {
}


protected void SelState( object sender, DirectEventArgs e ) {
// Populate control
var states = new List<string>() { "California", "Nevada", "Florida" };
ConvertStateToListener( states );
State.SelectText();
}
protected void SelCounty( object sender, DirectEventArgs e ) {
// Populate control
var state = State.Text;
var counties = new List<string>() { "Los Angeles", "Orange", "Ventura" };
ConvertCountyToListener( counties );
County.SelectText();
}
protected void ConvertStateToListener( List<string> arr ) {
ConvertEventToListener( State, arr );
}
protected void ConvertCountyToListener( List<string> arr ) {
ConvertEventToListener( County, arr );
}
protected void ConvertEventToListener( ComboBox ctl, List<string> arr ) {
var store = ctl.GetStore();
store.DataSource = arr.ConvertAll( input => new object[] { input } );
store.DataBind();
ctl.AllowBlank = false;
ctl.RemoveDirectListener( "focus" );
}
protected List<object[]> ConvertAll( IList<string> arr, string existing ) {
int len = arr.Count;
if( len == 0 )
return null;
var list = new List<object[]>( len - 1 );
for( int i = 0; i < len; i++ ) {
var item = arr[i];
if( existing == item )
continue;
list.Add( new object[] { item } );
}
return list;
}
[DirectMethod( IDMode = DirectMethodProxyIDMode.None, ShowMask = true )]
public void ChangeZRScope() {
RefreshZRScope( this, null );
}
public void RefreshZRScope( object sender, EventArgs args ) {
RegionRow.ReRender();
}
</script>


<!DOCTYPE html>
<html>
<head id="Head1" runat="server">
<title>Test44 Sample</title>
</head>
<body>
<form id="Form1" runat="server">


<ext:ResourceManager ID="ResourceManager1" runat="server" ScriptMode="Development" SourceFormatting="true" />
<ext:Viewport ID="vp" runat="server" Layout="HBoxLayout">
<Items>


<ext:Container ID="LP" runat="server" Border="true" Padding="5" Flex="1" Layout="FitLayout">
<Items>
<ext:FieldContainer ID="RegionRow" runat="server" AnchorHorizontal="100%" Layout="HBoxLayout" Cls="TitlePnl" PaddingSpec="0 5px 0 0">
<Items>


<ext:ComboBox ID="County" runat="server" DisplayField="County" ValueField="County" Flex="3" PaddingSpec="0 3px 0 0"
Editable="true" ForceSelection="true" QueryMode="Local"
EmptyText="Click for County" EmptyCls="EmptyReq">
<Store>
<ext:Store runat="server">
<Reader>
<ext:ArrayReader />
</Reader>
<Model>
<ext:Model runat="server">
<Fields>
<ext:ModelField Name="County" Type="String" SortDir="ASC" />
</Fields>
</ext:Model>
</Model>
</ext:Store>
</Store>
<DirectEvents>
<Focus OnEvent="SelCounty" Single="true">
<EventMask ShowMask="true" Msg="Loading Counties..." />
</Focus>
</DirectEvents>
<ToolTips>
<ext:ToolTip runat="server" Html="Select a county" />
</ToolTips>
</ext:ComboBox>


<ext:ComboBox ID="State" runat="server" DisplayField="State" ValueField="State" Flex="1"
Editable="true" ForceSelection="true" QueryMode="Local"
EmptyText="Click State" EmptyCls="EmptyReq">
<Store>
<ext:Store runat="server">
<Reader>
<ext:ArrayReader />
</Reader>
<Model>
<ext:Model runat="server">
<Fields>
<ext:ModelField Name="State" Type="String" SortDir="ASC" />
</Fields>
</ext:Model>
</Model>
</ext:Store>
</Store>
<DirectEvents>
<Focus OnEvent="SelState" Single="true">
<EventMask ShowMask="true" Msg="Loading States..." />
</Focus>
</DirectEvents>
<Listeners>
<Select Handler="App.direct.ChangeZRScope();;" />
<Focus Handler="#{State}.onTriggerClick();" />
</Listeners>
<ToolTips>
<ext:ToolTip runat="server" Html="Select a state" />
</ToolTips>
</ext:ComboBox>


</Items>
</ext:FieldContainer>
</Items>
</ext:Container>


</Items>
</ext:Viewport>
</form>
</body>
</html>

Daniil
Jan 17, 2014, 4:33 PM
Hi @michaeld,

Setting up some IDs explicitly for the Stores should help.

Autogenerated IDs are lost after a ReRender call.

michaeld
Jan 17, 2014, 10:02 PM
Setting up some IDs explicitly for the Stores should help.

Autogenerated IDs are lost after a ReRender call.

I thought I had checked to make sure ids didn't change but I may have not looked close enough that it could be the store. Thanks.

I'm surprised they find a way to change though. Anyway, that worked. You may close.

Daniil
Jan 30, 2014, 7:58 AM
Please also set up AutoDestroy="true" for the Store. Otherwise it won't be removed correctly.

michaeld
Jan 30, 2014, 12:21 PM
http://stackoverflow.com/questions/7473424/extjs4-autodestroy-for-stores
http://stackoverflow.com/questions/10525486/how-to-destroy-stores-in-extjs-4-1

Or did you guys add/override this functionality back in?

Daniil
Jan 30, 2014, 12:57 PM
If it was not used at some point, I think Sencha returned back the autoDestroy functionality. At least, it is used in the Bindable's bindStore method.
http://docs.sencha.com/extjs/4.2.1/source/Bindable.html#Ext-util-Bindable-method-bindStore


bindStore: function(store, initial, propertyName) {
// Private params
// @param {Boolean} [initial=false] True to not remove listeners from existing store.
// @param {String} [propertyName="store"] The property in this object under which to cache the passed Store.
propertyName = propertyName || 'store';

var me = this,
oldStore = me[propertyName];

if (!initial && oldStore) {
// Perform implementation-specific unbinding operations *before* possible Store destruction.
me.onUnbindStore(oldStore, initial, propertyName);

if (store !== oldStore && oldStore.autoDestroy) {
oldStore.destroyStore();
} else {
me.unbindStoreListeners(oldStore);
}
}
if (store) {
store = Ext.data.StoreManager.lookup(store);
me.bindStoreListeners(store);
me.onBindStore(store, initial, propertyName);
}
me[propertyName] = store || null;
return me;
};

Destroying of a ComboBox calls its bindStore(null). So, if a Store has "autoDestroy: true", it gets destroyed.

michaeld
Jan 30, 2014, 1:36 PM
Good to know. I'll be updating all to true. Though, I'm wondering if there's any intuition on your part why it would not be safe to set AutoDestroy=true as default on all stores bound to another control? It seems to me, most of your developers may find it pretty rare they manually destroy a control in the first place. I will be a lot now that I've been moving to the destroy-and-render ajax pattern. But the most likely someone would have a destroy would maybe be for controls inside a window. But wouldn't intuition hold that you'd pretty much always desire to have all connected stores destroyed with their control except when otherwise specified (false) instead of the other way around?

Daniil
Feb 03, 2014, 6:01 AM
You are right.

Now a Store's AutoDestroy is true by default, revision #5642. It will go to the v2.5 release.

michaeld
Feb 22, 2014, 1:31 AM
You are right.

Now a Store's AutoDestroy is true by default, revision #5642. It will go to the v2.5 release.


I saw that 5670 related to http://forums.ext.net/showthread.php?28109 had to deal with setting this to autodestroy back to false. From the code it looks like AutoDestroy is still set to true on the server-side for store controls but the javascript for ext-empty-store overrides it back to false. So basically everything is as stated above.

Just making sure nothing's changed.

Daniil
Feb 22, 2014, 6:02 AM
Yes, it is false just for the "ext-empty-store" which might be shared to many components. For other Stores it is still true by default.