ExtJs checkboxselectionmodel - extjs

I am using GridPanel w/CheckboxSelectionModel for item selection.
In the edit mode, where some options were already picked, I am trying to pre-select the rows when loading the form.
...
store.load();
//curSelections is an array containing the some ForeingKey IDs of the selected records.
...
for (var i = 0; i < curSelections.length; i++) {
console.log('found personel ' + curSelections[i] + ' at ',
store.findExact('Id', curSelections[i]));
selectedRecords.push(store.findExact('Id', curSelections[i]));
}
//everything is fine according to console log.
checkGrid.getSelectionModel().selectRecords(selectedRecords, true);
formWin.show();
this does not work.
I try to call" selectRecords" also on some other page/form events, but none of those even fires.
grid.addListener('show',
grid.on('show',
formWin.on('activate',
formWin.on('show',....
some of the grid code
var sm = new Ext.grid.CheckboxSelectionModel({
singleSelect: false,
sortable: false,
checkOnly: true
});
checkGrid = new Ext.grid.GridPanel({
xtype: 'grid',
store: obPersonelStore,
loadMask: true,
layout: 'fit',
height: 120,
id: 'grdIsBirimiPersonelListesi',
columns: [
sm,
{
I am missing something simple, but dont know what it is.
Any kind of help is greatly appreciated.

Store.findExact returns a numeric index. SelectionModel.selectRecords expects an array of Record objects. Have you tried selectRows instead? Either that, or use store.getAt to retrieve records by index to pass to selectRecords().

try:
var store = new Ext.data.Store({
...
});
var grid = new Ext.grid.GridPanel({
store: store,
...
});
store.on('load', function() {
grid.getSelectionModel().selectFirstRow();
});
store.load();

I'm not 100% certain what you want to achieve. You said:
I find the selected rows of the entire list
Do you mean you want to select every row? In that case you can use the selectAll() method of the CheckboxSelectionModel.
If you only want to select some of the rows then I'd need to see the code you're using to get those rows in the first place but it could be that you want to use selectRecords() rather than selectRows().

Related

EXTJS Spreadsheet Model - Keep row number column, but hide actual row numbers

I can't seem to figure out how to do this and google has been no help. I am using the ExtJS Spreadsheet model. I am trying to show the column with the row numbers, but I want to remove/hide the actual row numbers. I only want to keep the column that contain the row numbers. Any ideas on how I might go about doing this?
That should be easily done. As with every column, you have to add a custom renderer to the rownumberer column. So how do you get to that column?
For this, the spreadsheet selModel has a function getNumbererColumnConfig which you want to override. The unoverridden function from sources:
getNumbererColumnConfig: function() {
var me = this;
return {
xtype: 'rownumberer',
width: me.rowNumbererHeaderWidth,
editRenderer: ' ',
tdCls: me.rowNumbererTdCls,
cls: me.rowNumbererHeaderCls,
locked: me.hasLockedHeader
};
},
so, to override, you would do the following:
selModel: {
type: 'spreadsheet',
// Disables sorting by header click, though it will be still available via menu
columnSelect: true,
pruneRemoved: false,
extensible: 'y',
getNumbererColumnConfig: function() {
var me = this;
return {
xtype: 'rownumberer',
width: me.rowNumbererHeaderWidth,
renderer:function() { return ' '; },
editRenderer: ' ',
tdCls: me.rowNumbererTdCls,
cls: me.rowNumbererHeaderCls,
locked: me.hasLockedHeader
};
}
},
Tested in a Sencha fiddle

Dynamically changing the DataStore of a ComboBox

I have a combo box which populates its values based on the selection of another combobox.
I have seen examples where the params in the underlying store are changed based on the selection, but what I want to achieve is to change the store itself of the second combo based on the selection on the first combo. This is my code, but it doesn't work. Can someone please help?
{
xtype: 'combo',
id: 'leads_filter_by',
width: 100,
mode: 'local',
store: ['Status','Source'],
//typeAhead: true,
triggerAction: 'all',
selectOnFocus:true,
typeAhead: false,
editable: false,
value:'Status',
listeners:{
'select': function(combo,value,index){
var filter_to_select = Ext.getCmp('cmbLeadsFilter');
var container = filter_to_select.container;
if (index == 0){
filter_to_select.store=leadStatusStore;
filter_to_select.displayField='leadStatusName';
filter_to_select.valueField='leadStatusId';
} else if(index==1) {
filter_to_select.store=leadSourceStore;
filter_to_select.displayField='leadSourceName';
filter_to_select.valueField='leadSourceId';
}
}
}
},
{
xtype: 'combo',
id: 'cmbLeadsFilter',
width:100,
store: leadStatusStore,
displayField: 'leadStatusName',
valueField: 'leadStatusId',
mode: 'local',
triggerAction: 'all',
selectOnFocus:true,
typeAhead: false,
editable: false
},
That is not how its designed to work!! When you set a store in the config, you are binding a store to the combo. You don't change the store, instead you are supposed to change the data when required.
The right way of doing it would be to load the store with correct data from the server. To fetch data, you can pass params that will help the server side code get the set of options you need to load.
You will not want to change the store being used... Simply put, the store is bound to the control as it is instantiated. You can, however, change the URL, and params/baseParams used in any additional POST requests.
Using these params, you can code your service to return different sets of data in your combo box's store.
For the proposed problem you can try below solution :
Use below "listener" snippet for the first "leads_filter_by" combo. It will handle the dynamic store binding / changing for the second combobox.
listeners:{
'select': function(combo,value,index){
var filter_to_select = Ext.getCmp('cmbLeadsFilter');
var container = filter_to_select.container;
if (index == 0){
//filter_to_select.store=leadStatusStore;
filter_to_select.bindStore(leadStatusStore);
filter_to_select.displayField='leadStatusName';
filter_to_select.valueField='leadStatusId';
} else if(index==1) {
//filter_to_select.store=leadSourceStore;
filter_to_select.bindStore(leadSourceStore);
filter_to_select.displayField='leadSourceName';
filter_to_select.valueField='leadSourceId';
}
}
}
Hope this solution will help you.
Thanks & Regards.
I had a similar problem. The second combobox would load the store and display the values, but when I would select a value, it would not actually select. I would click the list item and the combobox value would remain blank.
My research also suggested that it was not recommended to change the store and field mappings on a combobox after initialization so here was my solution:
Create a container in the view that would hold the combobox to give me a reference point to add it back later
Grab a copy of the initial config off of the combobox ( this lets me set my config declaritively in the view and not hard code it into my replace function ... in case I want to add other config properties later)
Apply new store, valueField and displayField to that config
Destroy old combobox
Create new combobox with modified config
Using my reference from step 1, add the new combobox
view:
items: [{
xtype: 'combobox',
name: 'type',
allowBlank: false,
listeners: [{change: 'onTypeCombo'}],
reference: 'typeCombo'
}, { // see controller onTypeCombo for reason this container is necessary.
xtype: 'container',
reference: 'valueComboContainer',
items: [{
xtype: 'combobox',
name: 'value',
allowBlank: false,
forceSelection: true,
reference: 'valueCombo'
}]
}, {
xtype: 'button',
text: 'X',
tooltip: 'Remove this filter',
handler: 'onDeleteButton'
}]
controller:
replaceValueComboBox: function() {
var me = this;
var typeComboSelection = me.lookupReference('typeCombo').selection;
var valueStore = Ext.getStore(typeComboSelection.get('valueStore'));
var config = me.lookupReference('valueCombo').getInitialConfig();
/* These are things that get added along the way that we may also want to purge, but no problems now:
delete config.$initParent;
delete config.childEls;
delete config.publishes;
delete config.triggers;
delete config.twoWayBindable;
*/
config.store = valueStore;
config.valueField = typeComboSelection.get('valueField');
config.displayField = typeComboSelection.get('displayField');
me.lookupReference('valueCombo').destroy();
var vc = Ext.create('Ext.form.field.ComboBox', config);
me.lookupReference('valueComboContainer').add(vc);
},

Reconfigure GridPanel with grouping on GroupingStore

I have a problem with a GridPanel that uses a GroupingView:
var grid1 = new Ext.grid.GridPanel({
store: new Ext.data.GroupingStore({
fields: [ ]
}),
cm: new Ext.grid.ColumnModel([ ]),
selModel: new Ext.grid.RowSelectionModel({ singleSelect: false }),
view: new Ext.grid.GroupingView({
groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "' + BPS.Resource.items + '" : "' + BPS.Resource.item + '"]})'
})
});
I an event I call reconfigure that sets a new store and columnmodel. The store is a GroupingStore and I set what groupField i want to use:
// define the store
var store1 = new Ext.data.GroupingStore({
proxy: new Ext.data.HttpProxy({
url: listConfig.dataURL + '?sort=' + listConfig.defaultSortField + '&dir=' + listConfig.defaultSortDirection,
method: 'POST'
}),
autoLoad: false,
remoteSort: true,
remoteGroup: true,
groupOnSort: false,
groupField: listConfig.groupingColumn,
sortInfo: {
field: listConfig.defaultSortField,
direction: listConfig.defaultSortDirection
},
paramNames: {
start: 'skip',
limit: 'take',
sort: 'sort',
dir: 'dir'
},
reader: new Ext.data.JsonReader()
});
// reconfigure the grid
grid1.reconfigure(store1, new Ext.grid.ColumnModel(listConfig.columnDefinitions));
However, this seem to work the first time it's loaded. It sets grouping on a column, or no grouping at all if I haven't configured it. But after the user turn off grouping in the gridpanel and the same code runs in order to load the configuration it doesn't change it to be grouped.
What can I do to reconfigure the grid to use, or not use, grouping?
I was having issues with a groupingstore. When I modified a field of a record and the grouping was on that column where I modified the field from, the grid did not automatically regroup the records.
Also when adding a new row, the grouping was not correct, the record that was added did not get added in the correct group.
I solved this problem by keeping the current groupBy field in a global var and each time on update or afteredit and added events from the grid I unGrouped and then used groupBy() with the var that contains the current column where the store was grouped on.
Using only grid.getView().refresh(); didn't do the trick.
Question of course is, is this user friendly? Because each time that a field from a row is modified and the grouping is set on the column of that field that was modified, the record will get regrouped and the user might have problems finding the row he was modifying.
Better solution: Only unGroup and then use groupBy() with the var that stored the current groupBy column when the focus on the record that is being edited is lost. SO on the blur event.
I think you attach a listener to the GroupingStore's groupchange event and record the field that was chosen as the grouping field. Then when reconfiguring, you tell the store to group by that field with the groupBy() function or use the ungroup() function to remove the grouping. Then call the grid's view refresh() method.
Note that I haven't tested this so it may be complete rubbish! :-)

Extjs Dynamic Grid

I'm trying to create a dynamic grid using ExtJS. The grid is built and displayed when a click event is fired then an ajax request is sent to the server to fetch the columns, records and records definition a.k.a store fields.
Each node could have different grid structure and that depends on the level of the node in the tree.
The only way I came up with so far is :
function showGrid(response, request) {
var jsonData = Ext.util.JSON.decode(response.responseText);
var grid = Ext.getCmp('contentGrid' + request.params.owner);
if (grid) {
grid.destroy();
}
var store = new Ext.data.ArrayStore({
id: 'arrayStore',
fields: jsonData.recordFields,
autoDestroy: true
});
grid = new Ext.grid.GridPanel({
defaults: {
sortable: true
},
id: 'contentGrid' + request.params.owner,
store: store,
columns: jsonData.columns,
//width:540,
//height:200,
loadMask: true
});
store.loadData(jsonData.records);
if (Ext.getCmp('tab-' + request.params.owner)) {
Ext.getCmp('tab-' + request.params.owner).show();
} else {
grid.render('grid-div');
Ext.getCmp('card-tabs-panel').add({
id: 'tab-' + request.params.owner,
title: request.params.text,
iconCls: 'silk-tab',
html: Ext.getDom('grid-div').innerHTML,
closable: true
}).show();
}
}
The function above is called when a click event is fired
'click': function(node) {
Ext.Ajax.request({
url: 'showCtn',
success: function(response, request) {
alert('Success');
showGrid(response, request);
},
failure: function(results, request) {
alert('Error');
},
params: Ext.urlDecode(node.attributes.options);
}
});
}
The problem I'm getting with this code is that a new grid is displayed each time the showGrid function is called. The end user sees the old grids and the new one. To mitigate this problem, I tried destroying the grid and also removing the grid element on each request, and that seems to solve the problem only that records never get displayed this time.
if (grid) {
grid.destroy(true);
}
The behaviour I'm looking for is to display the result of a grid within a tab and if that tab exists replaced the old grid.
Any help is appreciated.
When you are trying to add your grid to the tab like this:
html:Ext.getDom('grid-div').innerHTML,
Ext is not aware of it being a valid grid component. Instead, you are simply adding HTML markup that just happens to look like a grid, but the TabPanel will not be aware that it is a grid component.
Instead you should add the grid itself as the tab (a GridPanel is a Panel and does not need to be nested into a parent panel). You can do so and also apply the needed tab configs like this:
Ext.getCmp('card-tabs-panel').add({
Ext.apply(grid, {
id: 'tab-' + request.params.owner,
title: request.params.text,
iconCls: 'silk-tab',
closable: true
});
}).show();
BTW, constantly creating and destroying grids is not an ideal strategy if you can avoid it. It might be better to simply hide and re-show grids (and reload their data) based on which type of grid is needed if that's possible (assuming the set of grid types is finite).
A potential option is to use the metaData field on the JsonStore that allows dynamic reconfiguring of the grid columns as per new datasets.
From
One of the most helpful blog posts about this that Ive found is this one:
http://blog.nextlogic.net/2009/04/dynamic-columns-in-ext-js-grid.html and the original info is well documented at http://docs.sencha.com/ext-js/3-4/#!/api/Ext.data.JsonReader

how to delete or add column in grid panel

grid.getcolumnModel().setHidden(0,true) will be effected for column menu
and not grid panel. In column menu u can enable or disable the column. How do we add or remove the column in grid panel dynamically?
I think this is what you are looking for http://www.extjs.com/forum/showthread.php?53009-Adding-removing-fields-and-columns
Make sure you look at post #37 in the thread as well.
For those who reach this question looking for a solution for Ext.js 4.2 and avobe.
I use "reconfigure" method to dynamically change the grid columns: http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.grid.Panel-method-reconfigure
Here is a nice example: http://marcusschiesser.de/2013/12/21/dynamically-changing-the-structure-of-a-grid-in-extjs-4-2/
You may have to refresh the Ext.grid.GridView in order for the column change to show.
grid.getView().refresh(true) // true to refresh HeadersToo
In ExtJs 3.x this piece of code can help:
Note: I have used checkbox, as the first column. Please remove that line if you don't need it.
var newColModel = new Ext.grid.ColumnModel({
columns: [
grid.getSelectionModel(),
{
header: 'New column 1'
}, {
header: 'New column 2'
}
],
defaults: {
sortable: false
}
});
grid.store.reader = new Ext.data.JsonReader({
root: 'items',
totalProperty: 'count',
fields: [
// Please provide new array of fields here
]
});
grid.reconfigure(grid.store, newColModel);
The reconfigure function might not work well with plugins. Especially if you have something like FilterBar.
If you only need to do this once, based on some global settings that use can use initComponent and change your initial config. Be sure to make all changes to the config before calling this.callParent();
Tested with ExtJS 6.2 (but should also work for ExtJS 4 and 5)
initComponent: function() {
// less columns for this setting
if (!app.Settings.dontUseFruits()) {
var newColumns = [];
for(var i=0; i<this.columns.items.length; i++) {
var column = this.columns.items[i];
// remove (don't add) columns for which `dataIndex` starts with "fruit"
if (column.dataIndex.search(/^fruit/) < 0) {
newColumns.push(column);
}
}
this.columns.items = newColumns;
}
this.callParent();
maybe try
store.add(new_record);
store.commitChanges();
or store.remove() and store.commitChanges()

Resources