I've a combobox which returns 10 values from DB;
Ext.define('Iso3Combo', {
extend:'',
xtype:'iso3combo',
requires: [
'Ext.data.proxy.Ajax',
'Ext.data.reader.Json'
],
name: iso3
fieldLabel: iso3,
displayField:'iso3', // takes from DB
valueField:'id', // takes from DB
store: {
proxy: {
type: 'ajax',
url: ...getUrl() + '/country/list',
reader: {
type: 'json',
rootProperty: 'data'
}
},
autoLoad: true
},
queryMode: 'local',
autoLoad:true,
bind: '{currRec.iso3}',
listeners: {
fn: function () {
console.log('isocombo listeners...');
},
select: this.getIso3,
change: this.getIso3,
scope: this
}
});
As you will notice above; combobox's displayed content is iso3 and gets id as primary key. Therefore I can not change valueField. So tried this function to reach some other value for that selected combobox record;
getIso3: function () {
var me = this;
// var rec = me.getSelectedRecords(); //says getSelectedRecords is not a function
var country = me.down('[name=iso3]').getValue(); // returns 'id'
// var isoCode = rec.data.iso3; //Couldn't be success to verify if I get correct value..
How can i be able to load all values of DB from selected combobox record and select one of them?
You need to use combobox.getSelection() or combobox.getSelectedRecord(). This both method will return you selected record. Or inside of select event you will get selected record in second parameter so also you can get iso3 value like this record.get('iso3').
Here is an FIDDLE, I have created a demo using form and combobox. This will help you or guide you to solve your problem.
I am using this COUNTRY JSON.
Code Snippet
// The data store containing the list of Country
var country = Ext.create('Ext.data.Store', {
fields: ['iso3', 'id'],
proxy: {
type: 'ajax',
url: 'countryList.json',
reader: {
type: 'json',
rootProperty: 'countrylist'
}
},
autoLoad: true
});
// Create form with the combo box, attached to the country data store
Ext.create('Ext.form.Panel', {
title: 'Country List Example with ComboBox',
bodyPadding: 10,
items: [{
xtype: 'combo',
fieldLabel: 'Choose Country',
store: country,
queryMode: 'local',
displayField: 'iso3',
valueField: 'id',
listeners: {
select: function (field, record) {
Ext.Msg.alert('Success', `Selected country <br> iso3 : <b>${record.get('iso3')}</b> <br> id : <b>${record.get('id')}</b>`);
}
}
}],
renderTo: Ext.getBody(),
buttons: [{
text: 'Get Combo Value/Record on button click',
handler: function () {
var record = this.up('form').down('combo').getSelectedRecord();
if (record) {
Ext.Msg.alert('Success', `Selected country <br> iso3 : <b>${record.get('iso3')}</b> <br> id : <b>${record.get('id')}</b>`)
} else {
Ext.Msg.alert('Info', 'Please select contry first.. :)');
}
}
}]
});
handler: function () {
var selectionmodel=this.up().down('multiselect');
var values=selectionmodel.values;
}
Related
I am solving a requirement which can be simplified as following. I am fairly new to Ext.js and I need help in achieving the below.
I have 4 tables as follows.
So, I have 3000 companies and 9000 users mapped across various companies. I need to map moderators for each company in a grid.
I have an add button, which adds a row in the grid.
I achieved displaying the companies in the first column of a grid. Easy. So user can pick one.
I achieved displaying users belonging to that company in the second column of the grid. FYI, User can multi select moderators here.
Problem:
At this point, when I add a new row, pick a new company, the companyusers store gets refreshed, so, the values selected in 1st row are not valid values anymore and the first row's user column is displaying empty text (or) only the id's
My models are as follows
Ext.define('Mine.CompanyModel', {
extend: 'Ext.data.Model',
fields: ['Id', {name: 'Name', type:'string'}]});
Ext.define('Mine.UsersModel', {
extend: 'Ext.data.Model',
fields: ['Id', {name: 'Name', type:'string'}]});
Ext.define('Mine.CompanyUsersModel', {
extend: 'Ext.data.Model',
fields: ['company_user_id', 'UserName']}); //<companyuser Id>
Ext.define('Mine.CompanyModeratorModel', {
extend: 'Ext.data.Model',
fields: ['Id', 'CompanyUserId']});
My stores are
Ext.define('Mine.CompanyStore', {
extend: 'Ext.data.Store',
model: 'Mine.CompanyModel',
autoLoad: true,
proxy: new Ext.data.HttpProxy({
url: '/somecontroller/someaction',
reader: {
type: 'json',
root: 'Data'
}
})
});
Ext.define('Mine.UsersStore', {
extend: 'Ext.data.Store',
model: 'Mine.UsersModel',
autoLoad: true,
proxy: new Ext.data.HttpProxy({
url: '/somecontroller/someaction',
reader: {
type: 'json',
root: 'Data'
}
}),
});
Ext.define('Mine.CompanyUserStore', {
extend: 'Ext.data.Store',
model: 'Mine.CompanyUserModel',
autoLoad: false,
proxy: new Ext.data.HttpProxy({
url: '/somecontroller/someaction',
reader: {
type: 'json',
root: 'Data'
}
}),
//will add extra params here
});
Ext.define('Mine.CompanyModeratorStore', {
extend: 'Ext.data.Store',
model: 'Mine.CompanyModeratorModel',
autoLoad: false,
proxy: new Ext.data.HttpProxy({
url: '/somecontroller/someaction',
reader: {
type: 'json',
root: 'Data'
}
}),
});
My grid columns are
{
text: 'Company', width: '10%', dataIndex: 'id',
renderer: companyRenderer(combo_company), editor: combo_company
},
{
text: 'Users', width: '16%', dataIndex: 'company_user_id',
renderer: companyUsersRenderer(companyUsersCbo), editor: companyUsersCbo
}
My editor is
var companyUsersCbo = Ext.create('Ext.form.ComboBox', {
xtype: 'combo',
id: 'company_users',
name: 'company_users',
valueField: 'Id',
displayField: 'name',
allowBlank: false,
store: 'Mine.CompanyUsersStore',
multiSelect: false,
editable: true,
queryMode: 'local',
pickerAlign: 'bl',
listConfig: {
getInnerTpl: function (display) {
return '<div class="x-combo-list-item"><img src="' + Ext.BLANK_IMAGE_URL + '" class="chkCombo-default-icon chkCombo" /> {' + display + '} </div>';
}
}
listeners: {
expand: function () {
var mainGrid = Ext.getCmp('mygrid');
var selmodel = mainGrid.getSelectionModel();
var record = selmodel.getSelection();
if (record[0].get('id') != null) {
this.getStore().getProxy().setExtraParam('company_id', record[0].get('id')); // am storing the company id in a model
this.getStore().load();
}
}
}
});
My renderer is
var companyUsersRenderer = function (combo) {
return function (resources) {
var result = [];
resources = resources || [];
for (var idx = 0, len = resources.length; idx < len; idx++) {
var value = combo.getStore().find(combo.valueField, resources[idx]);
if (value != -1) {
var rec = combo.getStore().getAt(value);
result.push(rec.get(combo.displayField));
}
}
return result.join(', ');
}
}
What am I missing? What should I do so that the values (names) displayed in the combo box remain independent of the next rows.
What have I tried:: I have added a separate hidden column and set it to the names, added to the record. It worked fine, but its not the correct way. Also, when I double click the cell for editing, it shows the numbers (id's and not text) but after I expand, it shows the text.
naga Sandeep,
try to send params with your URL to get filtered records.
like,
url:'someThing/abc/1435'+'id='+record.id;
filter your store accordingly.
Problem is when your grid is rendered, your columns are rendered and your render function uses last state of the combo's store.
I would add a display field to CompanyUsersModel then fill it when a company is selected. Also I would abandon renderer function.
I've created a script to dynamically generate a form, but I'm having problem loading the data of the nested model. I've tried loading the whole record and I've tried loading each sub store, but neither works.
I've through about using form.load(), but from my understanding that requires a proxy connection and also require to store json data inside a 'data' array.
Does anyone have any suggestions on how might I approach this problem?
<div id="view-#pageSpecificVar" class="grid-container even"></div>
<div id="button"></div>
<script>
Ext.define('HeaderForm', {
extend: 'Ext.form.Panel',
initComponent: function () {
var me = this;
Ext.applyIf(me, {
id: Ext.id(),
defaultType: 'textfield'
});
me.callParent(arguments);
}
});
// Define our data model
Ext.define('HeaderModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'HeaderSequence', type: 'int'}
],
hasMany:[
{ name: 'Columns', model: 'ColumnModel' }
],
proxy: {
type: 'ajax',
actionMethods: { create: 'POST', read: 'GET', update: 'POST', destroy: 'POST' },
url: '#Url.Content("~/Test/Header")',
timeout: 1200000,
},
});
Ext.define('ColumnModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'ColumnWidth', type: 'float'}
],
hasMany:[
{ name: 'Fields', model: 'FieldModel'}
],
belongsTo: 'HeaderModel'
});
Ext.define('FieldModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'XType', type: 'string'},
{ name: 'FieldLabel', type: 'string'},
{ name: 'Name', type: 'string'},
{ name: 'Data', type: 'string'},
{ name: 'FieldSpecify', type: 'bool'}
],
belongsTo: 'ColumnModel'
});
var store = Ext.create('Ext.data.Store', {
storeId: 'HeaderStore',
model: 'HeaderModel',
autoDestroy: true,
listeners: {
load: function (result, records, successful, eOpts) {
//console.log(result);
var form = dynamicForm(records[0]);
form.add(submitButton);
form.render('view-#pageSpecificVar');
}
}
});
store.load();
var dynamicForm = function(record) {
var form = new HeaderForm();
var columnContainer = new Ext.widget({
xtype: 'container',
layout: 'column'
});
var formItems = new Ext.util.MixedCollection();
Ext.each(record.ColumnsStore.data.items, function(item) {
Ext.iterate(item.data, function (key, value) {
var fieldContainer = new Ext.widget({
xtype: 'container',
columnWidth: value
});
Ext.each(item.FieldsStore.data.items, function(item) {
if(item.data["FieldSpecify"]) {
fieldContainer.add(new Ext.widget({
xtype: item.data["XType"],
fieldLabel: item.data["FieldLabel"],
name: item.data["Name"],
//value: item.data["Name"]
}));
}
}, this);
columnContainer.add(fieldContainer);
}, this);
}, this);
formItems.add(columnContainer);
form.add(formItems.items);
Ext.each(record.ColumnsStore.data.items, function(item) {
Ext.each(item.FieldsStore.data.items, function(fields) {
form.loadRecord(fields);
});
});
//form.loadRecord(record);
return form;
};
var submitButton = new Ext.widget({
xtype: 'toolbar',
dock: 'bottom',
items:[{
xtype: 'button',
text: 'Save',
handler: function(button) {
var basic = button.up('form').form;
basic.updateRecord(basic.getRecord());
var store = Ext.StoreMgr.get('HeaderStore');
store.each(function(record) {
record.dirty = true;
});
store.sync();
}
}]
});
</script>
Update
Sorry I probably didn't made it very clear. I'm having problem loading the store data into form fields. For static forms I normally use loadRecord to load the nested model into a form, but in this case all the fields are nested in their own little model, so would there be a way to load each nested model value into their own field with loadRecord?
The HeaderModel stores field set information.
The purpose of ColumnModel is to create the container that will surround a set of fields, for styling purpose. It simply creates two columns of fields.
The FieldModel stores the field specific attributes and data.
Here's an example of response json data...
{
"HeaderSequence":1,
"Columns":[{
"ColumnWidth":0.5,"Fields":[
{"XType":"textfield","FieldLabel":"FieldA","Name":"NameA","Data":"A","FieldSpecify":true},
{"XType":"textfield","FieldLabel":"FieldB","Name":"NameA","Data":"B","FieldSpecify":true}]
},{
"ColumnWidth":0.5,"Fields":[
{"XType":"textfield","FieldLabel":"FieldA2","Name":"NameA2","Data":"A2","FieldSpecify":true},
{"XType":"textfield","FieldLabel":"FieldB2","Name":"NameB2","Data":"B2","FieldSpecify":true}]
}
]
}
Thanks
I've figure out how to load the nested model into the form. We can't simply use load or loadRecord, as by default that method tries to get a model's data and iterate through the data object and call setValues.
What I have to do is manually get the basic form element and call setValues myself to assign the values.
// loop through each field store to load the data into the form by field id
Ext.each(record.ColumnsStore.data.items, function(item) {
Ext.each(item.FieldsStore.data.items, function(fields) {
form.getForm().setValues([{ id: fields.data['Id'], value: fields.data['DisplayName'] }]);
});
});
To Follow up with that, a custom submit handler needs to be put in place as well.
Which loops through the store and sets the submitted value to store before sync the store.
// define form submit button
var submitButton = new Ext.widget({
xtype: 'toolbar',
dock: 'bottom',
items:[{
xtype: 'button',
text: 'Save',
handler: function(button) {
// get basic form for button
var basic = button.up('form').form;
// get form submit values
var formSubmitValues = basic.getValues();
// get header store
var store = Ext.StoreMgr.get('HeaderStore');
// loop through each field store and update the data values by id from the form
store.each(function(record) {
Ext.each(record.ColumnsStore.data.items, function(item) {
Ext.each(item.FieldsStore.data.items, function(fields) {
fields.data['Data'] = formSubmitValues[fields.data['Id']];
});
});
// mark the record as dirty to be sync
record.dirty = true;
});
// sync store object with the database
store.sync();
}
}]
});
Have a look at this and this examples on how to load nested data into a nested model. You will also see how to access the associated data.
I'm not sure why you use record.ColumnsStore.data.items, as if record is of HeaderModel type, you should really get the columns store via record.Columns, and then iterate that store.
Would also help to see what JSON your server returns.
I have a following code for combo box, how can I get the value that is selected in the combobox and load that value into a variable, and use it later.
Thank you
Ext.define('Column', {
extend: 'Ext.data.Model',
fields: ['data1', 'Data2']
});
var store = Ext.create('Ext.data.Store', {
model: 'Column',
autoLoad: true,
proxy: {
type: 'ajax',
url: '/data.xml',
reader: {
type: 'xml',
record: 'result'
}
}
});
var simpleCombo = Ext.create('Ext.form.field.ComboBox', {
store: store,
displayField: 'data1',
valueField: 'data1',
width: 250,
labelWidth: 120,
fieldLabel: 'select a value',
renderTo: 'simpleCombo',
queryMode: 'local',
typeAhead: true
});
Simply use the select event
var simpleCombo = Ext.create('Ext.form.field.ComboBox', {
store: store,
displayField: 'data1',
valueField: 'data1' ,
width: 250,
labelWidth: 120,
fieldLabel: 'select a value',
renderTo: 'simpleCombo',
queryMode: 'local',
typeAhead: true,
listeners: {
select: function(combo, records) {
// note that records are a array of records to be prepared for multiselection
// therefore use records[0] to access the selected record
}
});
API Link
Additional content from the comments:
Take a look at the multiSelect property of the combobox. You get all values separated by a defined delimiter and the select event will give you a records array with more that one record. Note the that getValue() only give you the defined displayField which is a string and not the record itself. So using iComboValue[0] gives you the first character. The selected records should always be accessed using the selected event. But you may store them in a array for later use and overwrite it with any new select.
You can also use:
var iComboValue = simpleCombo.getValue();
may be you should try this
// to get the combobox selected item outside the combo listener
simpleCombo.on('change', function (combo, record, index) {
alert(record); // to get the selected item
console.log(record); // to get the selected item
});
I'm experimenting what seems to be a bug in ExtJS 4 Combobox AJAX Store.
I have a grid with articles, each article has a supplier and a category, each supplier offer articles that belong to a certain category. In order to filtre the grid i've put 2 Combos(Select Lists). One for supplier and one for category. These combos get their values by AJAX from a php script.
Everything went good till i tried to link the combos like this:
When the user selects a category from the combobox, the supplier Store refreshes with suppliers that offer that category (works fine!).
The the user selects a supplier from the combobox, and the category Store refreshes(refresh is good, as seen with firebug).
Here is my issue now, if the user selects the category combobox again it, the loading mask doesn't go away so it can't change the value of the combo.
I've tested and the AJAX is working fine, it's just a EXTJS 4 issue with the Loading Mask.
The issue is happening both ways:
A)
1. User selects a category
2. User selects a supplier
3. User CAN'T select a category(loading mask doesn't go away)
AND
B)
1. User selects a supplier
2. User selects a category
3. User CAN'T select a supplier(loading mask doesn't go away)
EDIT:
The problem seems to also occur on these situation(and vice-versa: supplier->category)
1. User selects a category
2. User changes the category
3. User CAN'T select a supplier(loading mask doesn't go away)
Here are my models:
Ext.define('Category', {
extend: 'Ext.data.Model',
fields: [
{ name: 'name'},
{ name: 'id'}
]
});
Ext.define('Supplier', {
extend: 'Ext.data.Model',
fields: [
{ name: 'name'},
{ name: 'id'}
]
});
Here are my stores:
var categoryStore = Ext.create('Ext.data.Store', {
model: 'Category',
autoLoad: true,
remoteSort: true,
proxy: {
type: 'ajax',
url: 'GetCategorysForSupplier',
reader: {
type: 'json',
root: 'items'
},
extraParams: {
supplier: 0
}
}
});
var supplierStore = Ext.create('Ext.data.Store', {
model: 'Supplier',
autoLoad: true,
remoteSort: true,
proxy: {
type: 'ajax',
url: 'getSuppliersForCategory.php',
reader: {
type: 'json',
root: 'items'
},
extraParams: {
category: 0
}
}
});
And here are my combos:
var categoryFilterCombo = Ext.create('Ext.form.field.ComboBox', {
xtype: 'combo',
store: categoryStore,
displayField: 'name',
valueField: 'id',
fieldLabel: 'Category Filter',
listeners: {
change: function(field,newVal) {
if (Ext.isNumeric(newVal)) {
supplierStore.proxy.extraParams.category = newVal;
articleStore.proxy.extraParams.category = newVal;
supplierStore.load();
articleStore.load();
}
}
}
});
var supplierFilterCombo = Ext.create('Ext.form.field.ComboBox', {
store: supplierStore,
displayField: 'name',
queryMode: 'local',
valueField: 'id',
fieldLabel: 'Supplier Filter',
listeners: {
change: function(field,newVal) {
if (Ext.isNumeric(newVal)) {
categoryStore.proxy.extraParams.supplier = newVal;
articleStore.proxy.extraParams.supplier = newVal;
categoryStore.load();
articleStore.load();
}
}
}
});
Kind Regards,
Dan Cearnau
Look here for the answer: http://www.sencha.com/forum/showthread.php?152324-4.0.7-ComboBox-bug-with-load-mask
There ldonofrio says:
This is a 4.0.7 bug, seems to be solved in 4.1pr
My override
PHP Code:
Ext.override(Ext.LoadMask, {
onHide: function() { this.callParent(); }
});
I am creating a grid panel and want to attach an event with each row. following is my code
var locationdata = Ext.create('Ext.data.Store', {
fields:['name'],
storeId:'simpsonsStore',
data:{'items':[
{ 'name': 'Lisa'}
]},
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'items'
}
}
});
hintBox = Ext.create('Ext.grid.Panel', {
title: 'Location List',
store: locationdata,
columns: [
{ header: 'Name', dataIndex: 'name' , flex:1 }
],
flex: 5
});
hintBox.getSelectionModel().on('rowselect', function(sm, rowIdx, r) {
alert("row selected");
});
I am adding hintBox in anothor panel which is rendered to body.
What is wrong with this code?
Selection model has no event 'rowselect', In Extjs 4 selectiom model has only selectionchange event.
hintBox.getSelectionModel().on('selectionchange', function(sm, selectedRows, opts) {
//selected rows is an array of models and if you want just one row selected,
//you have to config the grid so it only accepts one selection i think is selType: 'SINGLE' or 'SIMPLE'
// and after that selectedRows[0] will be the selected row
alert("rows selected");
});