I'm trying to edit an open source program (and learn Extjs meanwhile) and I encountered a problem about models. I don't want to put code here since it is too long but I can provide if necessary.
So I got a a class which extends Ext.form.Panel and model "PartModel" assigned to it. This model has a string field called "partNumber" along with many other fields.
In this panel I want to choose a part number from a combobox from predefined values at database and assign it to "partNumber".
The problem is I want to assign value that is "displayed" in the combobox.(Not one of store fields, I'm using a custom XTemplate for it)
How can I do it?
Edit: Adding combobox code. I thought adding "dataIndex: 'partNumber'" would be sufficient to do job but this code isn't working at all. I can see Part Numbers strings from combobox but when I choose one and hit save button it doesn't save. (There are many other fields working well with that save button maybe I just need to add another button to save part number?)
{
xtype: 'combobox',
dataIndex: 'partNumber',
fieldLabel: "Part Number",
labelWidth: 150,
flex: 1,
store:{
xtype: 'store',
autoLoad: true,
model: 'PartGroupsClasses',
proxy: getPartGC()},
queryMode: 'local',
renderTo:Ext.getBody(),
tpl:Ext.create('Ext.XTemplate','<tpl for="."><div class="x-boundlist-item">{code}-{descr}-{ccode}-{cdescr}</div></tpl>'),
displayTpl:Ext.create('Ext.XTemplate','<tpl for=".">{code}{descr}{ccode}{cdescr}</tpl>')
}
Edit2: Figured out save button is basically calling following function.
Ext.override(Ext.data.Model, {
setDataWithAssociations: function(data) {
for (var i in data) {
if (this.fields.containsKey(i)) {
this.set(i, data[i]);
}
if (this.associations.containsKey(i)) {
var store = this[i]();
store.add(data[i]);
}
}
}
});
I would do something like this... in your combobox's model, add an extra field that makes use of the convert function to create your displayValue, and then in your combobox, just use that value for your displayValue property.
Model
Ext.define('MyComboModel', {
extend: 'Ext.data.Model',
fields: [
{
name: 'code',
type: 'string'
},
{
name: 'desc',
type: 'string'
},
{
name: 'ccode',
type: 'string'
},
{
name: 'cdesc',
type: 'string'
},
{
name: 'displayValue',
type: 'string',
convert: function(value, record) {
return record.get('code') +
record.get('desc') +
record.get('ccode') +
record.get('cdesc');
}
}
]
});
Combo
xtype: 'combobox',
name: 'Field2',
valueField: 'displayValue',
displayField: 'displayValue',
fieldLabel: 'Field2',
queryMode: 'local',
Full example.
I dont thing your question is clear enough for a clear answer...
I am unclear on your objective but if you want to have something display on store and behind it have the value on the file please take a look see if this examples helps
Store
this.data = Ext.create('Ext.data.JsonStore', {fields: ['id', 'data'],
data: [{id: 1, data: 'data1'},
{id: 2, data: 'data2'},
{id: 3, data: 'data3'},
{id: 4, data: 'data4'}]});
Combo
xtype:'Combobox',
name:'wtv',
displayField: 'data',
valueField: 'id'
It will display the combo with data but if you get the combo with the selection path and do for example
Selector
refs: [{
ref:Combo
selector:'Panel Combobox[name=wtv]'
}]
Later you can do something like
Panel.getCombo().getValue() and it will not
give you back the displayed field (Data) but it will give the id.
Sorry for bad formating! Hope it helps
Related
I am using Ext JS 3.4 and in the composite field, there are three fields, code is as below:
xtype: 'compositefield',
name: 'comboField',
fieldLabel: 'Partner with',
width: 400,
cItems:[{
xtype: 'combo',
name: 'partnerTypeCombo',
value: 'ProviderName',
mode: 'local',
store: new Ext.data.ArrayStore({
fields: ['id', 'displayValue'],
data: [
['ProviderName', 'Provider Partner Name'],
['OtherProvider', 'Other Provider Partner']
]
}),
valueField: 'id',
displayField: 'displayValue',
listeners: {
scope: this,
select: function(combo, record, index) {
var providerField = this.formPanel.getForm().findField('comboField_providerPartnerNameField');
var otherProviderField = this.formPanel.getForm().findField('comboField_otherProviderPartnerNameField');
if (combo.value == "OtherProvider") {
providerField.setVisible(false);
otherProviderField.setVisible(true);
}
else {
providerField.setVisible(true);
otherProviderField.setVisible(false);
}
}
}
}, {
xtype: 'spacer',
width: 10,
flex: 0
}, {
xtype: 'modellinkfield',
name: 'providerPartnerNameField',
modelLevelType: 'Organization',
modelType: 'Organization',
pickerReport: {
reportName: 'TMS.SupplierVendorOrgPicker',
targetLevelType: 'Organization'
}
}, {
xtype: 'textfield',
name: 'otherProviderPartnerNameField',
hidden: true
}]
By using the above code and without hiding any field, I got the below result
But My expectation is
By default third field (which is text field) should be hidden
On selecting Combobox values, the next two fields should be visible/hidden.
Like if dropdown field value is "Provider Partner Name" then only second
field (modeling field) should be visible (shown as below)
And if dropdown field value is "Other Provider Name" then only third
field (i.e text field) should be visible.
But I am unable to achieve this third objective. I am getting the following output for this (the field is getting overridden)
And I am expecting the following output.
Looks like this may be some layout issue or maybe I need to apply some CSS style to handle this. Can someone please help me to solve this issue.
Able to solve this issue by using below code :
otherProviderField.ownerCt.doLayout();
I've come across a rather interesting problem. I have a store, which uses a model. My model looks like this:
Ext.define('HealOmni.model.device_model', {
extend: 'Ext.data.Model',
requires: [
'Ext.data.Field'
],
fields: [
{
name: 'device_id'
},
{
name: 'device_name'
},
{
name: 'device_id_real'
},
{
name: 'sim_number'
},
{
name: 'other_device_details'
},
{
convert: function(v, rec) {
return rec.get('device_name') + " " + rec.get('device_id_real');
},
name: 'device_name_and_id'
}
]
});
and then this store is used by a ComboBox, the combo box looks like this:
xtype: 'combobox',
height: 30,
itemId: 'deviceID',
fieldLabel: 'Device ID',
labelClsExtra: 'screenSharingFontLowerHalf',
labelSeparator: ' ',
displayField: 'device_name_and_id',
queryMode: 'local',
store: 'userDeviceManagementLoggedInDisplay',
valueField: 'device_id_real'
I use the combination field device_name_and_id as the display field of the combobox. However, when I reloaded my site, it seemed that the ComboBox could not display the field properly. When I use the other fields, let's say device_id, it displays just fine. It's only the combination field that does not display and I don't know why.
I log the values to console after I load the store and all fields are displayed, even the combination ones -- so I'm really rather confused as to why the ComboBox won't display properly.
Does anyone know how to show a "convert" field in a combobox?
Please check below fiddle
https://fiddle.sencha.com/#view/editor&fiddle/1m9t
Ext.define('HealOmni.model.device_model', {
extend: 'Ext.data.Model',
fields: [{
name: 'device_name_and_id',
convert: function (v, rec) {
return rec.get('device_name') + " " + rec.get('device_id');
}
}]
});
var storeRec = Ext.create('Ext.data.Store', {
model: 'HealOmni.model.device_model',
data: [{
device_id: 1,
device_name: 'device one with id'
}, {
device_id: 2,
device_name: 'device two with id'
}]
});
Ext.create('Ext.form.field.ComboBox', {
renderTo: Ext.getBody(),
valueField: 'device_id',
displayField: 'device_name_and_id',
store: storeRec
});
I've made a small fiddle for you. Compare this to your code, i hope it helps:
https://fiddle.sencha.com/#view/editor&fiddle/1m9e
In our application we have a lot of name/value stores, and they are created at load time and put into a JSONStore like so :
Ext.create("Ext.data.JsonStore", {
data: data,
model: 'EM.model.controlUnit.CodeList',
storeId: "cl_" + tableId,
sorters: [{
sorterFn: aSorterFunction
}],
});
The model is pretty simple and looks like this :
Ext.define('EM.model.controlUnit.CodeList', {
extend: 'Ext.data.Model',
fields: [{
name: 'value', type: 'int'
}, {
name: 'label', type: 'string'
}, {
name: 'description', type: 'string'
}]
});
I thought stores were pretty interchangeable so I decided to use the store in the combo (There is no special combo store so I thought a JSONStore must be as good as a SimpleStore). I get the store like so :
var msDataStore = Ext.getStore("cl_t_cl_maritalstatus");
And use the store like so :
{
xtype: 'combo',
fieldLabel: 'Marital Status',
displayField: "label",
valueField: "value",
store: msDataStore
}
The combo is filled with the values from the store when I run the application, however, when I pop down the combo box, this error is thrown :
ext-debug-w-comments.js:9951 Uncaught
Ext.data.proxy.Server.buildUrl(): You are using a ServerProxy but have
not supplied it with a url.
I do not want any server proxy. These are simple locally stored name value collections.
Can JSONStores be used with combos?
If not. What is the best way to convert a JSONStore into something acceptable for the combo. I can chop, change, restructure the store object. But I just want to know if there is something simpler that I can do before going on some kind of long and pointless journey.
This problem is related 'proxy' property. Default proxy for JsonStore is 'ajax';
proxy: {
type : 'ajax',
reader: 'json',
writer: 'json'
}
You should override with 'memory' like that;
proxy: {
type: 'memory'
}
Your final store is;
Ext.create("Ext.data.JsonStore", {
data: data,
model: 'EM.model.controlUnit.CodeList',
storeId: "cl_" + tableId,
proxy: {
type: 'memory'
}
sorters: [{
sorterFn: aSorterFunction
}],
});
A JsonStore without URL is completely acceptable, but you have to make sure the combo does not trigger a load operation when clicking on the dropdown. This is done by adding to the combo definition the config option queryMode:'local':
{
xtype: 'combo',
fieldLabel: 'Marital Status',
displayField: "label",
valueField: "value",
queryMode: 'local',
store: msDataStore
}
This is a 2-part question:
Primary Question: Say I have a combobox (code below) that is pulling from a store. Say I have an array that I want to filter the data by so that only certain values actually show up in the dropdown. I can't seem to find the parameter that will do that... Is there a simple way to do this?
Secondary question: I also need to be able to disable and reenable items within the drop down based on actions of the user after the dropdown is created. Is there a function that causes items to be reenabled/disabled within the dropdown?
Note: By disabled I mean 'not present' aka removed in the dom, but still present in the non-filtered store.
{
xtype: 'combobox',
anchor: '100%',
name: 'Permission_id',
fieldLabel: 'Permissions',
hideLabel: false,
displayField: 'Name',
forceSelection: true,
store: 'PermissionStore',
typeAhead: true,
valueField: 'id',
valueNotFoundText: 'Add Permission'
}
I think all you need is work with filters. If you want to display only certain values in the dropdown, the only thing you have to do is filter the store and if what yo have is an array, you can use an ArrayStore for that.
About your second question, if you filter your store, original values are not lost, they are save internally as an snapshot then when you clear your filters, old values are displayed again in the dropdonlist.
Please take a look at this working example: http://jsfiddle.net/lontivero/Mz6S4/1/
First answer: the method is .filter(). For example:
var store = Ext.create('Ext.data.ArrayStore', {
fields: ['Id', 'Name'],
data: [
[ 1, 'Lucas' ],
[ 2, 'Pablo' ],
[ 3, 'Francisco' ]
]
});
Ext.create('Ext.form.field.ComboBox', {
fieldLabel: 'Permissions',
displayField: 'Name',
store: store,
valueField: 'Id',
renderTo: Ext.getBody()
});
//Hide Pablo in the dropdownlist
store.filter([
{filterFn: function(record) { return record.get('Name') !== 'Pablo'; }}
]);
// uncomment this to reenable hidden records (to display Pablo again)
//store.clearFilter();
Second answer: clear the store's filters
As lontivero said, filters solve your issue:
primary: array can contain data but filter will hide it from the dropdown
secondary: filters can be changed to hide and show in the dropdown
Your remaining problem, then, is how to change the filter from non-Ext code. Here you can use the fact that Ext is just javascript and can be called from any other javascript that has nothing to do with Ext.
So:
Add some functions that apply the filters to add and remove, in a place/scope that is accessible to the HTML DOM
Add them to the onclick handlers of the (plain HTML) buttons
The trick is really to access the store by using the Ext lookup by id.
So if the following code (extending on lontivero's jsfiddle) is directly in a js file (or in a script tag), it does what you're asking for:
(jsfiddle: http://jsfiddle.net/mCv6A/)
// functions that do the filtering
var noPablo = function(record) { return record.get('Name') !== 'Pablo' }
var noJames = function(record) { return record.get('Name') !== 'James' }
// the combination of functions we'll use
var withoutJamesFilter = [{ filterFn: noPablo }, { filterFn: noJames }]
var withJamesFilter = [{ filterFn: noPablo }]
function addJames()
{
var store = Ext.getStore('people')
store.clearFilter()
store.filter(withJamesFilter)
}
function delJames()
{
var store = Ext.getStore('people')
store.clearFilter()
store.filter(withoutJamesFilter)
}
Ext.onReady(function()
{
var store = Ext.create('Ext.data.ArrayStore', {
id: 'people',
fields: ['Id', 'Name'],
data: [
[ 1, 'Lucas' ],
[ 2, 'Pablo' ],
[ 3, 'Francisco' ],
[ 4 , 'James' ]
]
})
Ext.create('Ext.form.field.ComboBox', {
fieldLabel: 'Permissions',
displayField: 'Name',
store: store,
valueField: 'Id',
renderTo: Ext.getBody()
})
// start without james in list
store.filter(withoutJamesFilter)
})
Things to consider when using it for real (rather than in a simplified example):
wrapping addJames, delJames and the variables (noPablo, noJames etc) they use in an object or immediate function so the variables don't clutter the global (window) scope
rewriting the filter variables to better share implementation (something like a function that takes a list of names and generates a filter array or filter function that filters out those names would be sensible)
I'm working with ExtJS 4.1, I need to create a combo box containing a list of customers and I'd like to set a specific pre-selected item in it, but I don't know how to do it.
Here's the code to create my combo box:
xtype: 'combobox',
fieldLabel: 'customer',
name: 'customer_id',
allowBlank:false,
afterLabelTextTpl: required,
//data store
store: Ext.create('Ext.data.Store', {
autoDestroy: true,
model: 'customer_model',
autoLoad: true,
proxy: {
type: 'ajax',
url: 'load.php?item=customer',
reader: {
type: 'json',
successProperty: 'success',
root: 'data'
}
}
}),
valueField: 'id',
displayField: 'company',
typeAhead: true,
queryMode: 'remote',
emptyText: ''
As you can see my combo box is filled by a data store, that data store is built on a data model called 'customer_model'. Here's the code for data model:
Ext.define('customer_model', {
extend: 'Ext.data.Model',
fields: [
{type: 'int', name: 'id'},
{type: 'string', name: 'company'},
{type: 'string', name: 'vat'},
{type: 'string', name: 'ssn'},
{type: 'int', name: 'ref_id'}
]
});
Well, I'd like to configure my combo box so that a certain item, for instance the customer having id equals to 1, is automatically selected when the page is loaded.
Can anyone help me ?
Thanks in advance.
Enrico.
In Ext.js 3.2.1, you are able to do this:
combobox.setValue(id);
This assumes that the combobox is configured to use id as the valueField. Your code seems to indicate that this is the case. You would also need to have a reference to the id value that you want to set the value to. The caveat here is that you need to make sure that this code only executes after the model is loaded, otherwise the combobox won't have anything to display. You can ensure this by setting the combobox in the callback method of the ajax call or in the load event of the store.
I've looked into the documentation for Ext.js 4.1, and this method seems to still be there. I believe this should do the trick.
Edit: clarity
Thanks to Christopher help I wrote a working version of my code, I've decided to post it here, maybe it could be useful for someone...:
buttons: [{
text: 'Load',
handler: function(){
var form = this.up('form').getForm();
var combobox = form.findField('ref_id_combo');
formPanel.getForm().load({
url: <?php echo "'update_loader.php?id=".$_GET['id']."&item=customer',"; ?>
waitMsg: 'Loading...',
success: function(form, action) {
combobox.setValue(<?php echo get_property_id("ref_id","customer",$_GET['id']);?>);
}
});
}
}
Programatically with combo.setValue(val) or declaratively:
{
xtype: 'combo',
value: val,
...
}
if you want to select the first value of a store you can do
combo.select(combo.getStore().getAt(0))
it will select the value at index 0 of the combo store
If you create your own store first, you can use afterrender: function(combo){}
listeners: {
afterrender: function (combo) {
var record = yourStore.getAt(0);
var abbr= record.get('abbr');
combo.setValue(abbr);
}
}