Combobox inside Extjs editor grid panel while populating is invisible sometimes - extjs

Hi all I am using Extjs 3.4 my problem is I have one editor grid panel
and inside panel I have one department combobox. So, in first page I
have search grid and on click of grid I am coming to this page and on
load using ajax I am populating combobox value in grid panel. But sometimes
values are not coming, means it is invisible and only after clicking on that
combobox it is appearing. Can some body explain what is the problem.
Thanks in advance, I hope will get reply soon.
While populating I am calling one ajax which is populating values in grid but
there is no issue with other columns, only with combobox it is invisible sometimes
Ext.util.Format.comboRenderer = function(Departmentscombo){
return function(value){
var record = combo.findRecord(combo.valueField || combo.displayField, value);
return record ? record.get(combo.displayField) : combo.valueNotFoundText;
}
}
Ext.grid.ComboColumn = Ext.extend(Ext.grid.Column, {
constructor: function(cfg){
Ext.grid.ComboColumn.superclass.constructor.call(this, cfg);
this.renderer = Ext.util.Format.comboRenderer(this.editor.field ?
this.editor.field : this.editor);
}
});
Ext.apply(Ext.grid.Column.types, {
combocolumn: Ext.grid.ComboColumn
});
var DepartmentsJReader = new Ext.data.JsonReader
({ root: 'data', id: 'mastercode' },
[{ name: 'mastercode' }, { name: 'description'}]);
Departments_store = new Ext.data.Store
({
proxy: new Ext.data.HttpProxy(
{ url: '', method: 'GET' }),
reader: DepartmentsJReader, autoLoad: true,
listeners:
{
load: function () {
var rec = new Departments_store.recordType({ mastercode:'-', description: '-' });
rec.commit();
Departments_store.insert(0, rec);
Departments_store.commitChanges();
}
}
});

Related

Extjs 5 grid sync row render issues

using extjs 5.1.0
My issues, when I add value to store of grid and then call store.sync()
inserted row become selected (visually) but I cannot select it for edit or darg&drop row for sorting, only helps reload grid.
here is my store:
var store = Ext.create('Ext.data.ArrayStore', {
model: 'pbxe.module.conference.ConferenceModel',
proxy: {
type: 'direct',
api: {
read: pbxe._conference.read,
create: pbxe._conference.create,
update: pbxe._conference.update,
destroy: pbxe._conference.destroy,
},
reader: {
rootProperty: 'data',
totalProperty: 'totalCount',
successProperty: 'success',
messageProperty: 'message'
},
writer: {
writeAllFields: true,
},
},
autoSync: false,
autoLoad: true,
});
We ran into same problem, seems there is an issue of the Selection Model keeping a map of the records added to the store which can't get "deselected".
So with a bit of brute force:
// WORKAROUND for grid / selection model problem
// after adding multiple new records with Store.sync()
//var grid = grid bound to this store...
myStore.sync(
{
scope: this,
success: function (batch, options) {
var sm = grid.getSelectionModel();
var records = batch.operations[0].getRecords();
if (sm && sm.selected)
{ // deselect does not work as has bug leaves new records in map
sm.selected.map = {}; //wipe clear the selected records map
}
sm.select(records);
}
});
Hope this helps - works for us in Ext JS 5.1.0

Apply grid filter programmatically from function

Using Ext.ux.grid.FiltersFeature, I have remote filters and I am trying to write a function to apply a date filter on a grid column programmatically (rather than clicking on the filter drop down menu in the column header). The first time I run the function the grid store gets reloaded without the filter. When I run the function a second time (and every time thereafter) it works totally fine, the store reloads with the filters. Here is the gist of the function I have:
// a filter object for testing
aFilter = {type: 'date', field: 'a_date_field', comparison: 'gt', value: '2012-03-08 00:00:00'}
var grid = Ext.create('Ext.grid.Panel', {
store: store,
features: [{
ftype: 'filters',
}],
columns[{
header: 'ID',
dataIndex: 'id',
itemId: 'id',
width: 40,
}, {
xtype: 'datecolumn',
header: 'Date',
dataIndex: 'a_date_field',
itemId: 'a_date_field',
width: 75,
format:'j-M-Y',
filterable: true
}],
listeners: {
'afterrender': function() {
// Need to create the filters as soon as the grid renders
// rather than waiting for the user to click on the header
grid.filters.createFilters();
}
},
bbar: [{
text: 'Do a filter',
handler: function() {
// get the filter that is attached to the grid
var gridFilter = grid.filters.getFilter(aFilter.field);
// have to do this to create a menu for this filter
gridFilter.init({dataIndex: aFilter.field, type: aFilter.type, active: true});
// if this column is a date filter column
if (gridFilter.type == 'date') {
var dateValue = Ext.Date.parse(aFilter.value, 'Y-m-d H:i:s');
if (filter.comparison == 'gt') {
gridFilter.setValue({after: dateValue});
} else {
gridFilter.setValue({before: dateValue});
}
}
}
}
});
I also found that this function works the first time if I click on any grid header menu before I run the function.
I've been trying to find out what changes are made to the grid which make the filter work after the first attempt fails or what clicking on any grid header does to make it work. But nothing I add seems to fix it so it will run the first time. Has anyone implemented this successfully?
I have workaround:
bbar: [{
text: 'Do a filter',
handler: function() {
var grid = this.up('grid');
var dateValue = Ext.Date.parse(aFilter.value, 'Y-m-d H:i:s');
var value = aFilter.comparison == 'gt' ? {after: dateValue} : {before: dateValue};
var gridFilter = grid.filters.getFilter(aFilter.field);
if (!gridFilter) {
gridFilter = grid.filters.addFilter({
active: true,
type: aFilter.type,
dataIndex: aFilter.dataIndex,
});
gridFilter.menu.show();
gridFilter.setValue(value);
gridFilter.menu.hide();
} else {
gridFilter.setActive(true);
}
Ext.Function.defer(function(){
gridFilter = grid.filters.getFilter(aFilter.field);
gridFilter.setValue(value);
}, 10);
}
}]
As you can see I actually apply filter 2 times.
As an update, I expanded this function and modified it to work with ExtJS 4.1.1
Here is an example of the function to set grid filters dynamically (without the user needing to click on the menu items). Afterwards, the filtered items will be visible to the user in the grid column header menus as if he clicked on them and set them manually.
The "grid" argument is a grid with FiltersFeature that you want to filter. The other argument is an array of "filter" objects (I'll show an example below), the function simply applies all the passed "filter" objects to the grid.
doGridFilter: function(grid, filters) {
// for each filter object in the array
Ext.each(filters, function(filter) {
var gridFilter = grid.filters.getFilter(filter.field);
gridFilter.setActive(true);
switch(filter.data.type) {
case 'date':
var dateValue = Ext.Date.parse(filter.data.value, 'm/d/Y'),
value;
switch (filter.data.comparison) {
case 'gt' :
value = {after: dateValue};
break;
case 'lt' :
value = {before: dateValue};
break;
case 'eq' :
value = {on: dateValue};
break;
}
gridFilter = log.filters.getFilter(filter.field);
gridFilter.setValue(value);
gridFilter.setActive(true);
break;
case 'numeric':
var value;
switch (filter.data.comparison) {
case 'gt' :
value = {gt: filter.data.value};
break;
case 'lt' :
value = {lt: filter.data.value};
break;
case 'eq' :
value = {eq: filter.data.value};
break;
}
gridFilter = log.filters.getFilter(filter.field);
gridFilter.setValue(value);
gridFilter.setActive(true);
break;
case 'list':
gridFilter = log.filters.getFilter(filter.field);
gridFilter.menu.setSelected(gridFilter.menu.selected, false);
gridFilter.menu.setSelected(filter.data.value.split(','), true);
break;
default :
gridFilter = log.filters.getFilter(filter.field);
gridFilter.setValue(filter.data.value);
break;
}
});
}
Here's an example of a "filter" object array.
// an example of a "filters" argument
[{
field: 'some_list_column_data_index',
data: {
type: 'list',
value: 'item1,item2,item3,item4,item5,item6,item7'
}
}, {
field: 'some_date_column_data_index',
data: {
type: 'date',
comparison: 'gt',
value: '07/07/2007'
}
}]
One caveat, you need to "create" the filters manually before using this function. Normally FiltersFeature grid filters are "created" the first time a user clicks on one of them, that may not happen if the user just wants to apply one of these predefined filters.
That can be handled easily by including this afterrender listener in the gridpanel.
listeners: {
// must create the filters after grid is rendered
afterrender: function(grid) {
grid.filters.createFilters();
}
}
Just add
filter: true
to grid columns description like this:
me.columns = [
{header:"Name", dataIndex:"name", editor:"textfield", filter: true},
];
if you want to get the filter work after the first attempt, first instance create.
Here is something that may be worth looking into. It seems that the filters plugin is listening for menucreate event to initialize the filters. I wonder if menu create event is deferred until necessary and hence the filters don't get initialized?
/**
* #private Handle creation of the grid's header menu. Initializes the filters and listens
* for the menu being shown.
*/
onMenuCreate: function(headerCt, menu) {
var me = this;
me.createFilters(); //<------
menu.on('beforeshow', me.onMenuBeforeShow, me);
},
Do you want to apply grid filter or may be store.filter() capability would suit you better? In this case just filter the store, and grid will display filtered records.
I discovered another way to implement this. It appears that grid features are only bound to the grid after the grid is rendered. This means that any setup of the filter will not take effect until after the grid is rendered. The initial load of the store appears to be initiated before the grid is rendered.
I solved my problem by creating my store with a memory proxy containing no data.
me.store = Ext.create('Ext.data.Store', {
model: 'SummaryData',
data: [],
proxy: {
type: 'memory',
reader: 'array'
},
remoteSort: true,
remoteFilter: true
});
Then set up an afterrender handler on the grid to poke in the correct proxy and initiate a load of the store.
afterrender: function () {
var me = this;
me.store.setProxy({
type: 'ajax',
url : '/print_unallocated/change_site__data',
reader: {
type: 'json',
root: 'rows'
},
listeners: {
exception: function (proxy, response) {
Max.reportException(response);
}
}
});
me.filters.createFilters();
me.store.load();
},
In the source, you can see a comment related to this.
// Call getMenu() to ensure the menu is created, and so, also are the filters. We cannot call
// createFilters() withouth having a menu because it will cause in a recursion to applyState()
// that ends up to clear all the filter values. This is likely to happen when we reorder a column
// and then add a new filter before the menu is recreated.
me.view.headerCt.getMenu();
You can test whether the menu has been created before applying your filter. If it hasn't, do it yourself.
if(!grid.getView().headerCt.menu){
grid.getView().headerCt.getMenu();
}

EXTJS GridPanel Inside Window Is Not Loading Updated Data From Store When Window is Re-Opened

I have an EXT form that opens a window containing an GridPanel where the data store needs to get updated each time the form is submitted. The grid displays a list of files that are uploaded from the client computer. All of this works fine until I close the window and select a different group of files. The problem I am having is when the window containing the grid is closed and then re-opened, it is displaying the first set of files loaded previously instead of the new list of files submitted from the form. Hopefully this makes sense.
I have tried grid.getView().refresh() but that doesn't update the grid. Below is my code for the window, form, grid, and JSON store. If anyone has seen this before I would sure appreciate some advice. (apologies for the code formatting...had a lot of trouble getting it to be readable this text box)
//window that holds grid
SPST.window.POGCheckInWindow = Ext.extend(SPST.window.WindowBaseCls, {
id: 'POGCheckInWindow'
,initComponent:function() {
var config = {
title: 'Check In POG Files'
,width : 1000
,height : 500
,maximizable: false
,shadow : false
,closeable: true
,closeAction: 'hide'
,items: [{
xtype : 'checkin_results_grid'
,id : 'POGCheckInGrid'
,height : 450
,width : 990
,frame : true }
]};
Ext.apply(this, Ext.apply(this.initialConfig, config));
SPST.window.POGCheckInWindow.superclass.initComponent.apply(this, arguments);
}
});
Ext.reg('pog_checkin_window',SPST.window.POGCheckInWindow);
//function to submit the form, load the store and open the window containing the gridpanel
checkin:function() {
if (this.getForm().isValid()){
this.getForm().submit({
url: 'components/POG.cfc?method=uploadPOGTemp' + '&dsn=' + SPST_dsn
,method: 'GET'
,scope:this
,success: function(form, action){
var chkinwin = new SPST.window.POGCheckInWindow();
Ext.getCmp('POGCheckInGrid').getStore().load({params: {dsn: SPST_dsn,
pogfiles: action.result.pogfiles, project_id: action.result.project_id}
,callback: function(rec, options, success){
Ext.getCmp('POGCheckInGrid').getView().refresh();
}
});
chkinwin.show();
}
,failure:this.showError
,waitMsg:'Uploading files...'
});
}
}
// create the data store for grid
var chkstore = new Ext.data.JsonStore({
// JsonReader configuration
root : 'jsonlist'
,fields : chkfields
,id : 'chkstoreid'
// JsonStore configuration
,autoLoad : true
,remoteSort : true
,autoDestroy: true
,sortInfo: {
field: 'POGNAME',
direction: 'ASC'
}
,url : 'components/POG.cfc?method=getPOGTempFiles' + '&dsn=' + SPST_dsn
});
//grid that loads inside ext window
SPST.grid.POGCheckInGrid = Ext.extend(SPST.grid.GridPanelBaseCls, {
view: new Ext.grid.GridView({
getRowClass: function(rec, idx, rowPrms, ds)
{
return rec.data.VERSION_DSC === 'INVALID VERSION#' ? 'invalid-cls' : '';
}
}),
initComponent : function() {
var config = {
colModel : chkcolModel
,selModel : chkselModel
,store : chkstore
,autoDestroy: true
,xtype : 'checkin_results_grid'
,buttons: [
{
text: 'Upload'
,handler: this.loadPOGCheckin
,scope : this
},
{
text: 'Cancel'
,handler: this.checkinwindowclose
,scope : this
}
]
}
Ext.apply(this, Ext.apply(this.initialConfig, config));
SPST.grid.POGCheckInGrid.superclass.initComponent.apply(this, arguments);
}
,onRender : function() {
this.getBottomToolbar().bindStore(chkstore);
SPST.grid.POGCheckInGrid.superclass.onRender.apply(this, arguments);
}
From what I understood, you don't need to only refresh the view, but also reload the store according to the different set of files that you selected..
So, instead of doing
grid.getView().refresh() use grid.getStore().reload([new-options-if-required]);.. This will reload the store according to the options passed, if any, or reload the store according to the last load options.

ExtJS: Linked combobox puzzle

I write special combo object to use it as linked combos. Here it is:
comboDivClass = Ext.extend(Ext.form.ComboBox, {
fieldLabel: 'Divisions',
anchor: '95%',
lazyRender:true,
store:new Ext.data.Store({
proxy: proxy,
baseParams:{rfb_type:'divisions'},
reader: divReader,
autoLoad: true
}),
displayField:'div_name',
allowBlank:false,
valueField:'div_id',
triggerAction:'all',
mode:'local',
listeners:{
select:{
fn:function(combo, value) {
if (this.idChildCombo) {
var modelCmp = Ext.getCmp(this.idChildCombo);
modelCmp.setValue('');
modelCmp.getStore().reload({
params: { 'div_id': this.getValue() }
});
}
}
}
},/**/
hiddenName:'div_id',
initComponent: function() {comboDivClass.superclass.initComponent.call(this);}})
As you may see, this combobox load data at child combobox store(which set as idChildCombo).
Ok. Here is how i declare it
new comboDivClass({id:'sub0div',idChildCombo:'sub1div'}),
new comboDivClass({id:'sub1div'})
Yes it works, but it have some odd trouble - it load not only sub1div store, it load at sub0div store too. Why? What im doing wrong?
One thing I see is that you have mode: 'local' config, while it should be remote.
Other thing to consider: Why don't you do it more like this:
var c1 = new comboDivClass({id:'sub0div'});
var c2 = new comboDivClass({id:'sub1div'});
c1.on('select',function(combo, value) {c2.getStore().reload({
params: { 'div_id': c1.getValue() }
})});
ChildCombo.setMasterField( masterField ) {
masterField.on('change', function(field){
this.getStore().filterBy( function(){ //filter by masterFIeld.getValue() } );
})
}
The idea is to link child field to parent not parent to child and this way you can link to any kind form field no only combo.
Here in child combo you have to have store with three columns [group,value,label] where group is value of master field.
This way you can manage to have mode than one master field.

How to apply seriesStyles to piechart in ExtJs dynamically

Am trying to set 'seriesstyles' to piechart dynamically from the JSON data. When the 'oneWeekStore' loads the JSON data, I wish to iterate through the 'color' of each record and setSeriesStyles dynamically to PieChart. Below is the snippet.
var oneWeekStore = new Ext.data.JsonStore({
id:'jsonStore',
fields: ['appCount','appName'],
autoLoad: true,
root: 'rows',
proxy:storeProxy,
baseParams:{
'interval':'oneWeek',
'fromDate':frmDt.getValue()
},
listeners: {load: {
fn:function(store,records,options) {
/*I wish iterate through each record,fetch 'color'
and setSeriesStyles. I tried passing sample arrays
as paramater to setSeriesStyles like
**colors= new Array('0x08E3FE','0x448991','0x054D56');
Ext.getCmp('test12').setSeriesStyles(colors)**
But FF throws error "this.swf is undefined". Could
you please let me know the right format to pass as
parameter. */
}
});
var panel = new Ext.Panel{
id: '1week', title:'1 week',
items : [
{ id:'test12',
xtype : 'piechart',
store : oneWeekStore,
dataField : 'appCount',
categoryField : 'appName',
extraStyle : {
legend:{
display : 'right',
padding : 5,
spacing: 2, font :color:0x000000,family:
'Arial', size:9},
border:{size :1,color :0x999999},
background:{color: 0xd6e1cc}
} } } ] }
My JSON data looks below:
{"success":true,"rows":[{"appCount":"9693814","appName":"GED","color":"0xFB5D0D"},{"appCount":"5731","appName":"SGEF"","color":"0xFFFF6B"}]}
Your guidance is highly appreciated
You have a classic race condition there - your setting an event in motion that relies on a Component who's status is unknown.
The event your setting off is the loading of the data Store, when that has finished loading it is trying to interact with the Panel, but at that point we don't know if the Panel has been rendered yet.
Your best bet is to make one of those things happen in reaction to the other, for example:
1 ) load the store
2 ) on load event fired, create the panel
var oneWeekStore = new Ext.data.JsonStore({
id:'jsonStore',
...,
listeners: {
load:function(store,records,options) {
var panel = new Ext.Panel({
...,
seriesStyles: colors,
...
});
}
}
});
or
1 ) create the panel (chart)
2 ) on render event of the panel, load the store (remove autoLoad:true)
var panel = new Ext.Panel({
id: '1week',
...,
listeners: {
render: function(pnl){
oneWeekStore.load();
}
}
});
Hope that helps.

Resources