PDA

View Full Version : [CLOSED] Binding a Custom Search ComboBox



RCN
May 22, 2012, 8:31 PM
Hi folks, when the button1 Button is clicked the data is loaded and linked to the form. The ID and Name properties work properly but i would like to load a "SubRecord" of ComboBox when binding SubEntityID property. In other words, i would like to know how to load the entity and select the entity that the ComboBox is Linked - as a DropDownList selects a child element.

4274

1 - View


<ext:FormPanel ID="FormPanel1" runat="server" Title="Form Panel" Width="300">
<Items>
<ext:TextField ID="TextField1" Name="ID" FieldLabel="ID" AnchorHorizontal="100%"
runat="server" />
<ext:TextField ID="TextField2" Name="Name" FieldLabel="Name" AllowBlank="false" AnchorHorizontal="100%"
runat="server" />
<ext:ComboBox ID="ComboBox1" Name="SubEntityID" FieldLabel="SubEntity" runat="server" DisplayField="ID" ValueField="Name" MinChars="1" AnchorHorizontal="100%">
<ListConfig LoadingText="Searching...">
<Tpl ID="Tpl1" runat="server">
<Html>
<tpl for=".">
<tpl if="[xindex] == 1">
<table class="cbStates-list">
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</tpl>
<tr class="x-boundlist-item">
<td>{ID}</td>
<td>{Name}</td>
</tr>
<tpl if="[xcount-xindex]==0">
</table>
</tpl>
</tpl>
</Html>
</Tpl>
</ListConfig>
<Store>
<ext:Store ID="Store1" runat="server" AutoLoad="false">
<Proxy>
<ext:AjaxProxy Url="/Example/LoadComboItems/">
<ActionMethods Read="POST" />
<Reader>
<ext:JsonReader Root="data" TotalProperty="total" />
</Reader>
</ext:AjaxProxy>
</Proxy>
<Model>
<ext:Model ID="Model1" runat="server">
<Fields>
<ext:ModelField Name="ID" />
<ext:ModelField Name="Name" />
</Fields>
</ext:Model>
</Model>
</ext:Store>
</Store>
</ext:ComboBox>
</Items>
<Buttons>
<ext:Button ID="button1" runat="server" Text="Old">
<Listeners>
<Click Handler="loadRecord(false);" />
</Listeners>
</ext:Button>
</Buttons>
<Bin>
<ext:Store ID="Store2" runat="server" AutoLoad="false" PageSize="1">
<Model>
<ext:Model ID="Model2" IDProperty="ID" runat="server">
<Fields>
<ext:ModelField Name="ID" />
<ext:ModelField Name="Name" />
<ext:ModelField Name="SubEntityID" />
</Fields>
</ext:Model>
</Model>
</ext:Store>
</Bin>
</ext:FormPanel>


2 - Javascript


<script type="text/javascript">
var loadRecord = function (loadNew) {

Ext.net.DirectMethod.request({
url: "/Example/LoadEntity",
cleanRequest: true,
params: {
loadNew: loadNew
},
success: function (result) {
App.Store2.loadRawData(result);

var record = App.Store2.getAt(0);

App.FormPanel1.getForm().loadRecord(record);
}
});
}
</script>


3 - Controller


public AjaxResult LoadEntity(bool loadNew)
{
AjaxResult ajx = new AjaxResult();

if (loadNew)
{
ajx.Result = new Person();
}
else
{
ajx.Result = new Person { ID = 1, Name = "EXT", SubEntityID = 123 };
}

return ajx;
}

public StoreResult LoadComboItems(int start, int limit, string sort, string dir, string filter)
{
List<Person> lst = new List<Person>();

for (int index = start; index < limit; index++)
{
lst.Add(new Person
{
ID = index,
Name = "Name" + index,
});
}

return new StoreResult(lst, lst.Count());
}


4 - Entity


public class Person
{
public int ID { get; set; }

public string Name { get; set; }

public int SubEntityID { get; set; }
}

RCN
May 22, 2012, 9:03 PM
Going further. The ComboBox has no data loaded and i try to edit an Entity and i load the entity´s data in the form. All properties are linked properly but i need to load a "sub entity" to the ComboBox.

Daniil
May 23, 2012, 9:57 AM
Hi,

Well, I would remove Name of the ComboBox and call the load method for its Store.

App.FormPanel1.getForm().loadRecord(record);
App.ComboBox1.getStore().load({
params : {
id : record.get("SubEntityID")
}
});

RCN
May 24, 2012, 4:30 PM
It works, but when i open the ComboBox it does a query with no filter. I want that it just show the loaded record. It´s possible to achieve it using doQuery method instead of load method but in this case the ComboBox is expanded.

Any ideas?

Daniil
May 24, 2012, 7:00 PM
Does setting up

TriggerAction="Query"
for the ComboBox help?

See also
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.form.field.ComboBox-cfg-triggerAction (http://docs.sencha.com/ext-js/4-1/#%21/api/Ext.form.field.ComboBox-cfg-triggerAction)

Just a quick question - do you really need ComboBox if you need to just show a value? Or, maybe, a solution is making the ComboBox not expandable (at least, temporary)?

RCN
May 25, 2012, 12:05 PM
Here is my situation (fake example). When the button _btnEdit is clicked, the record is loaded into FormPanel and then the ComboBox´s record is loaded. if the user opens the ComboBox just the loaded entity must be shown - the default behaviour is performing query. But if the user change the query the ComboBox will perform query and show the result.

In the following example, press button _btnEdit and then expand the ComboBox. just the associated record is gonna be shown. but if you change the query it will perform query normaly.

I achieved it by setting allQuery property when loading FormPanel record and cleaning it when DirtyChange event occurs.

do you think that this is a valid approach? do you have another way to accomplish this task?

1 - View


<ext:ResourceManager ID="ResourceManager1" runat="server" />
<ext:FormPanel ID="FormPanel1" runat="server" Title="Form Panel" Width="300">
<Items>
<ext:TextField ID="TextField1" Name="ID" FieldLabel="ID" AnchorHorizontal="100%"
runat="server" />
<ext:TextField ID="TextField2" Name="Name" FieldLabel="Name" AllowBlank="false" AnchorHorizontal="100%"
runat="server" />
<ext:ComboBox ID="ComboBox1" Name="SubEntityID" TriggerAction="All" FieldLabel="SubEntity" runat="server"
DisplayField="Name" ValueField="ID" MinChars="1" AnchorHorizontal="100%">
<ListConfig LoadingText="Searching...">
<Tpl ID="Tpl1" runat="server">
<Html>
<tpl for=".">
<tpl if="[xindex] == 1">
<table class="cbStates-list">
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</tpl>
<tr class="x-boundlist-item">
<td>{ID}</td>
<td>{Name}</td>
</tr>
<tpl if="[xcount-xindex]==0">
</table>
</tpl>
</tpl>
</Html>
</Tpl>
</ListConfig>
<Store>
<ext:Store ID="Store1" runat="server" AutoLoad="false">
<Proxy>
<ext:AjaxProxy Url="/Example/LoadComboItems/">
<ActionMethods Read="POST" />
<Reader>
<ext:JsonReader Root="data" TotalProperty="total" />
</Reader>
</ext:AjaxProxy>
</Proxy>
<Model>
<ext:Model ID="Model1" runat="server">
<Fields>
<ext:ModelField Name="ID" />
<ext:ModelField Name="Name" />
</Fields>
</ext:Model>
</Model>
</ext:Store>
</Store>
<Listeners>
<Select Handler="this.getTrigger(0).show();" />
<BeforeQuery Handler="this.getTrigger(0)[this.getRawValue().toString().length == 0 ? 'hide' : 'show']();" />
<DirtyChange Handler="App.ComboBox1.allQuery = '';" />
<TriggerClick Handler="if (index == 0) {
this.clearValue();
this.getTrigger(0).hide();
}" />
</Listeners>
<Triggers>
<ext:FieldTrigger Icon="Clear" Tag="Limpar" HideTrigger="true" />
</Triggers>
</ext:ComboBox>
</Items>
<Buttons>
<ext:Button ID="_btnEdit" runat="server" Text="Edit entity">
<Listeners>
<Click Handler="loadRecord(false);" />
</Listeners>
</ext:Button>
<ext:Button ID="_btnCreate" runat="server" Text="Create entity">
<Listeners>
<Click Handler="loadRecord(true);" />
</Listeners>
</ext:Button>
</Buttons>
<Bin>
<ext:Store ID="Store2" runat="server" AutoLoad="false" PageSize="1">
<Model>
<ext:Model ID="Model2" IDProperty="ID" runat="server">
<Fields>
<ext:ModelField Name="ID" />
<ext:ModelField Name="Name" />
<ext:ModelField Name="SubEntityID" />
</Fields>
</ext:Model>
</Model>
</ext:Store>
</Bin>
<Listeners>
</Listeners>
</ext:FormPanel>


2 - JavaScript


var loadRecord = function (loadNew) {

Ext.net.DirectMethod.request({
url: "/Example/LoadEntity",
cleanRequest: true,
params: {
loadNew: loadNew
},
success: function (result) {

App.Store2.loadRawData(result);

var record = App.Store2.getAt(0);

App.FormPanel1.getForm().loadRecord(record);

var valor = App.ComboBox1.getRawValue();

if (valor != null && valor > 0) {
App.ComboBox1.allQuery = "*" + App.ComboBox1.getSubmitValue();

App.ComboBox1.doQuery(App.ComboBox1.allQuery);

App.ComboBox1.collapse();
}
}
});
}


3 - Controller


public AjaxResult LoadEntity(bool loadNew)
{
AjaxResult ajx = new AjaxResult();

if (loadNew)
{
ajx.Result = new Person();
}
else
{
ajx.Result = new Person { ID = 1, Name = "EXT", SubEntityID = DateTime.Now.Second };
}

return ajx;
}

public StoreResult LoadComboItems(int start, int limit, string query)
{
List<Person> lst = new List<Person>();

if (query.StartsWith("*"))
{

lst.Add(new Person
{
ID = Convert.ToInt32(query.Substring(1)),
Name = "Name -- " + query,
});
}
else
{
for (int index = start; index < limit; index++)
{
lst.Add(new Person
{
ID = index,
Name = "Name" + DateTime.Now.Millisecond,
});
}
}

return new StoreResult(lst, lst.Count());
}


3 - Entity


public class Person
{
public int ID { get; set; }

public string Name { get; set; }

public Nullable<int> SubEntityID { get; set; }
}

RCN
May 25, 2012, 12:48 PM
Going further, it would be nice if i could set lastValue, rawValue and lastQuery ComboBox´s properties. There is no affect when these properties are set programaticaly. it could be easier to accomplish my needs if it was possible

Daniil
May 25, 2012, 4:00 PM
Well, your approach looks good. Though, personally, I would implement it a bit different.

ComboBox

<ext:ComboBox
ID="ComboBox1"
runat="server"
TriggerAction="All"
FieldLabel="SubEntity"
DisplayField="Name"
ValueField="ID"
MinChars="1"
AnchorHorizontal="100%">
<ListConfig LoadingText="Searching...">
<Tpl ID="Tpl1" runat="server">
<Html>
<tpl for=".">
<tpl if="[xindex] == 1">
<table class="cbStates-list">
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</tpl>
<tr class="x-boundlist-item">
<td>{ID}</td>
<td>{Name}</td>
</tr>
<tpl if="[xcount-xindex]==0">
</table>
</tpl>
</tpl>
</Html>
</Tpl>
</ListConfig>
<Store>
<ext:Store ID="Store1" runat="server" AutoLoad="false">
<Proxy>
<ext:AjaxProxy Url="/Test/LoadComboItems/">
<ActionMethods Read="POST" />
<Reader>
<ext:JsonReader Root="data" TotalProperty="total" />
</Reader>
</ext:AjaxProxy>
</Proxy>
<Model>
<ext:Model runat="server">
<Fields>
<ext:ModelField Name="ID" />
<ext:ModelField Name="Name" />
</Fields>
</ext:Model>
</Model>
</ext:Store>
</Store>
<Listeners>
<Select Handler="this.getTrigger(0).show();" />
<BeforeQuery Handler="this.getTrigger(0)[this.getRawValue().toString().length == 0 ? 'hide' : 'show']();
if (this.showJustSelectedValue) {
this.expand();
return false;
}" />
<Change Handler="this.showJustSelectedValue = false;" />
<TriggerClick Handler="if (index == 0) {
this.clearValue();
this.getTrigger(0).hide();
}" />
</Listeners>
<Triggers>
<ext:FieldTrigger Icon="Clear" Tag="Limpar" HideTrigger="true" />
</Triggers>
</ext:ComboBox>

JavaScript

var loadRecord = function (loadNew) {
Ext.net.DirectMethod.request({
url : "/Test/LoadEntity",
cleanRequest : true,
params : {
loadNew : loadNew
},
success : function (result) {
var store = App.Store2,
record,
formPanel = App.FormPanel1,
combo = App.ComboBox1;

store.loadRawData(result);
record = store.getAt(0);
formPanel.getForm().loadRecord(record);
combo.getStore().load({
params : {
id : record.get("SubEntityID")
},
callback : function (records, operation, success) {
combo.setValue(records[0].get(combo.valueField));
combo.showJustSelectedValue = true;
}
});
}
});
};

Controller Action

public StoreResult LoadComboItems(int start, int limit, int? id)
{
List<Person> lst = new List<Person>();

if (id != null)
{

lst.Add(new Person
{
ID = id.Value,
Name = "Name -- " + id,
});
}
else
{
for (int index = start; index < limit; index++)
{
lst.Add(new Person
{
ID = index,
Name = "Name" + DateTime.Now.Millisecond,
});
}
}

return new StoreResult(lst, lst.Count());
}

The rest things stay the same.

Daniil
May 25, 2012, 4:10 PM
Going further, it would be nice if i could set lastValue, rawValue and lastQuery ComboBox´s properties. There is no affect when these properties are set programaticaly. it could be easier to accomplish my needs if it was possible

lastValue

This is a private property and should not not used directly. Though I can imagine the scenario where it might be useful to read it. But I think it should not be changed.

rawValue

This is a private property and should not not used directly. You can use the getRawValue and setRawValue methods.

lastQuery

Well, this is a public property and changing it directly makes sense. Here is an example when it can be changed.
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.form.field.ComboBox-property-lastQuery

RCN
May 25, 2012, 5:08 PM
Hi Danill, thank you for your time.

i just have one more issue. please do the following test (shown in the video bellow)


Load Record
Expand the Combobox - The record is shown (OK)
Press the clear trigger
Expand the Combobox - The records are shown (OK)
Press ESC
Load Record
Expand the Combobox - The record is shown (OK)
Press the clear trigger
Expand the Combobox - Just the loaded record is shown. it is expected that it performs query as it did in step4.




http://www.dailymotion.com/video/xr3wyd_ext001_tech

Daniil
May 28, 2012, 12:22 PM
Thanks for the detailed steps and video.

I would also clear the lastQuery within the Change listener.

<Change Handler="this.showJustSelectedValue = false;
delete this.lastQuery;" />