EXT Grid with multiple checkboxes - Selecting item deselects another - extjs

I have a EXT JS 4.2 grid 5 columns, it has the normal selection checkbox at the far left along with an additional checkbox in the second to last column and a radio in the last column.
If I click and select a row in the selection column then go to click the 'Primary' radio or 'Full' checkbox it will unselect whatever is already selected on that row. For instance, if I select row 1 then go to click the Primary Radio it will unselect, then if I click on Full it will deselect the Radio. Then If click on the Radio again and then Full they will stay selected.
It seems like once the checkbox or radio are selected a second time it begins to act normally, not sure why this behaviour is occuring or how to correct it.
I have tried adding the checkOnly: true paramater but that did not seem to do anything different.
Here is the code for the Grid:
Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.selection.CheckboxModel'
]);
Ext.onReady(function(){
Ext.QuickTips.init();
// Data store
var data = Ext.create('Ext.data.JsonStore', {
autoLoad: true,
fields: [ 'name', 'market', 'expertise', 'id', 'isFull', 'isPrimary'],
proxy: {
type: 'ajax',
url: '/opsLibrary/getLibraryJson'
}
});
// Selection model
var selModel = Ext.create('Ext.selection.CheckboxModel', {
columns: [
{xtype : 'checkcolumn', text : 'Active', dataIndex : 'id'}
],
checkOnly: true,
mode: 'multi',
enableKeyNav: false,
listeners: {
selectionchange: function(value, meta, record, row, rowIndex, colIndex){
var selectedRecords = grid4.getSelectionModel().getSelection();
var selectedParams = [];
// Clear input and reset vars
$('#selected-libraries').empty();
var record = null;
var isFull = null;
var isPrimary = null;
// Loop through selected records
for(var i = 0, len = selectedRecords.length; i < len; i++){
record = selectedRecords[i];
// Is full library checked?
isFull = record.get('isFull');
// Is this primary library?
isPrimary = record.get('isPrimary');
// Build data object
selectedParams.push({
id: record.getId(),
full: isFull,
primary: isPrimary
});
}
// JSON encode object and set hidden input
$('#selected-libraries').val(JSON.stringify(selectedParams));
console.log(JSON.stringify(selectedParams));
}}
});
// Render library grid
var grid4 = Ext.create('Ext.grid.Panel', {
xtype: 'gridpanel',
id:'button-grid',
store: data,
forceSelection : false,
autocomplete: false,
typeAhead: false,
columns: [
{text: "Library", width: 170, sortable: true, dataIndex: 'name'},
{text: "Market", width: 125, sortable: true, dataIndex: 'market'},
{text: "Expertise", width: 125, sortable: true, dataIndex: 'expertise'},
{text: 'Full', dataIndex:'isFull', checkOnly: true, width: 72,
renderer: function (value, meta, record) {
return '<center><input type="checkbox" onclick="var s = Ext.getCmp(\'button-grid\').store; s.getAt(s.findExact(\'id\',\'' + record.get('id') + '\')).set(\'isFull\', this.value)"'
}},
{text: 'Primary', dataIndex:'isPrimary', checkOnly: true, width: 72,
renderer: function(value, meta, record)
{
return '<center><input type="radio" onclick="var s = Ext.getCmp(\'button-grid\').store; s.getAt(s.findExact(\'id\',\'' + record.get('id') + '\')).set(\'isPrimary\', this.value)"'
}},
],
columnLines: false,
selModel: selModel,
width: 600,
height: 300,
frame: true,
title: 'Available Libraries',
iconCls: 'icon-grid',
renderTo: Ext.get('library-grid')
});
});
Any help would be greatly appreciated....
Thanks!

I think problem is that your render functions for checkbox and radio columns are not bound to the state of your model, and each time they are rendered the boxes are shown as unchecked.
Try to add 'checked' attribute to your boxes in render functions if value in model is true e.g.:
return '<center><input type="checkbox" ' + (value ? 'checked' : '') + ' onclick=.....
This should bring consistency to the functionality at least.

Related

EXTJS 4.2 grid get column header name on cell click with custom multi cell selection model

I have already tried grid.getColumnModel().getColumnHeader(columnIndex); but this doesn't work. I am using a custom grid selection model.I want to get column header value whenever any cell in corresponding column is clicked
You need to add cellClick listener to the panel, here is the modified code
var grid1 = Ext.create('Ext.grid.Panel', {
renderTo: Ext.getBody(),
store: store,
width:0.3*Ext.getBody().getViewSize().width,
height: 0.5*Ext.getBody().getViewSize().height,
columnLines: true,
columns: [{
text : 'Company',
locked : true,
sortable : false,
dataIndex: 'company',
renderer : function (value, metaData, record, row, col, store,gridView) {
metaData.tdAttr = 'data-qtip="' + value + '"';
return value;
}
},{
text : 'Price',
width : 125,
locked:true,
sortable : true,
renderer : 'usMoney',
dataIndex: 'price',
},{
text : 'Change',
width : 555,
sortable : true,
dataIndex: 'change',
renderer : function (value, metaData, record, row, col, store, gridView) {
metaData.tdAttr = 'data-qtip="' + value + '"';
return value;
}
},{
text : '% Change',
width : 555,
sortable : true,
renderer : pctChange,
dataIndex: 'pctChange',
},{
text : 'Last Updated',
width : 555,
sortable : true,
renderer : Ext.util.Format.dateRenderer('m/d/Y'),
dataIndex: 'lastChange'
}],
title: 'Locking Grid Column',
selType: 'cellmodel',
selModel: Ext.create('MyApp.MultiCellSelectionModel',{
mode: 'MULTI',
allowDeselect: true
}),
multiSelect: true,
listeners : {
cellclick( grid, cell, columnIndex, record , node , rowIndex , evt){
var cellId = grid.getHeaderCt().getHeaderAtIndex(columnIndex).id;
var dataIndex = grid.getHeaderCt().getHeaderAtIndex(columnIndex).dataIndex;
var text = grid.getHeaderCt().getHeaderAtIndex(columnIndex).text;
alert(dataIndex);
alert(text);
}
}
});

hide combo box value when already selected extjs

I have 2 combo box inside grid. The second combo box value will be change base on first combo box.
For example the combo has 3 item : America, Europe, Asia. If in the first combo box Europe is selected, then in the second combo box, Europe is not appear again.
I don't know which version of extjs I used, but here's the code :
MY COMBO STORE
var cb_group = Ext.create('Ext.data.Store', {
model: 'cb_group',
autoLoad: false,
proxy: {
type: 'ajax',
url: 'srv/master/group/combo',
reader: {
type: 'json',
root: 'rows'
}
}
});
MY COMBO INSIDE GRID
var set_approval_dtl = Ext.create('Ext.Window', {
title: title_approval2, width: 850, height: 395, rowdblclick: true, forceFit: true,
closeAction: "hide", store: ms_set_approval_dtl_store,
defaults: {
sortable: true, resizable: false
},
items: [
{xtype: "form", items: [
{layout: 'column', columnWidth: .5, itemId: 'set_approve', defaults: {border: false},
items: [{xtype: "panel", itemId: "set_approve_panel", height: 330, defaultType: 'textfield', margin: '0 10px 0 10px',
defaults: {labelWidth: 120, width: 850, maxLength: 200},
items: [
{xtype: "grid", itemId: "grid_items", width: 782, height: 280, margin: '0 10px 10px 10px', autoScroll: true,
plugins: Ext.create('Ext.grid.plugin.CellEditing', {clicksToEdit: 1, pluginId: 'rowEditing'}),
store: ms_set_approval_dtl_store, stripeRows: true, defaultType: "gridcolumn",
viewConfig: {forceFit: true},
columns: [
{header: grid18j, width: 150, dataIndex: 'nm_act', align: 'center'},
{header: subtitle_approval3, width: 126, dataIndex: 'level1', align: 'center',
editor: {xtype: "combobox", name: "cdgr", itemId: "cdgr1", typeAhead: true, editable: false, triggerAction: "all", forceSelection: true,
emptyText: grid8k, store: cb_group, valueField: "id", displayField: "nm",
listeners: {
expand: function(field, options, val) {
if (Ext.typeOf(field.getPicker().loadMask) !== "boolean") {
field.getPicker().loadMask.hide();
}
},
select: function(value) {
var obj = this.lastSelection[0].data;
return obj.nm;
this.lastSelection[0].hide;
cb_group.removeAt(0);
}
}},
renderer: function(val) {
var index = cb_group.findExact('id', val);
if (index !== -1) {
var rs = cb_group.getAt(index).data;
return rs.nm;
}
}
},
{header: subtitle_approval4, width: 126, dataIndex: 'level2', align: 'center', itemId: "level2",
editor: {xtype: "combobox", name: "cdgr", itemId: "cdgr2", typeAhead: true, editable: false, triggerAction: "all", forceSelection: true,
emptyText: grid8k, store: cb_group, valueField: "id", displayField: "nm",
listeners: {
expand: function(field, options) {
if (Ext.typeOf(field.getPicker().loadMask) !== "boolean") {
field.getPicker().loadMask.hide();
}
}
}
},
select: function(value) {
var obj = this.lastSelection[0].data;
return obj.nm;
},
renderer: function(val) {
var index = cb_group.findExact('id', val);
if (index !== -1) {
var rs = cb_group.getAt(index).data;
return rs.nm;
}
}
}]
}]}
]}]}
]});
I've tried this.lastSelection[0].hide; and cb_group.removeAt(0); in the first combo. But it didn't work at all. And I dont know why my select listener is not working.
please share some solution. Thanks
You can use XTemplates to manage this kind of behavior with one store and two comboboxes.
At first you have to create an XTemplate for your list of items in the combobox:
// displayfield = displayfield configured in your combobox
var template = Ext.create('Ext.XTemplate',
'<tpl for=".">',
' <tpl if="[Ext.getCmp(\'combobox1\').getValue()] != id && [Ext.getCmp(\'combobox2\').getValue()] != id">',
' <div class="x-boundlist-item">{label}</div>',
' <tpl else>',
' <tpl if="id == null || id == \'\'">',
' <div class="x-boundlist-item">{label}</div>',
' <tpl else>',
' <div class="x-boundlist-item" style="font-size:0px; height:0px;"></div>',
' </tpl>',
' </tpl>',
'</tpl>'
);
The XTemplate contains some statements to check if the specific value is already selected in one of the comboboxes. If not, then the entry will appear in the dropdown list, otherwise it will be hidden. To make it work, you have to set the template in your combobox and add some listeners to them:
// Combobox 1
{
xtype: 'combo',
id: 'combobox1',
store: 'your_store',
tpl: template,
displayField: 'label',
valueField: 'id',
listeners: {
beforeSelect: function (combo, record, index, eOpts)
{
// Check if the selected value is already selected in combobox2
var cbx2value = !!Ext.getCmp('combobox2').getValue() ? Ext.getCmp('combobox2').getValue() : '';
if (cbx2value != record.get('id') && cbx2value != record.get('id')) {
return true; // selected entry will be selected successfully
} else {
return false; // selected entry will not be selected
}
},
change: function ()
{
// Get the picker (list of items) of the other combobox and refresh it's template state
var cbx2picker = Ext.getCmp('combobox2').getPicker();
cbx2picker.refresh();
}
}
// Combobox 2
{
xtype: 'combo',
id: 'combobox2',
store: 'your_store',
tpl: template,
displayField: 'label',
valueField: 'id',
listeners: {
beforeSelect: function (combo, record, index, eOpts)
{
// Check if the selected value is already selected in combobox2
var cbx1value = !!Ext.getCmp('combobox1').getValue() ? Ext.getCmp('combobox1').getValue() : '';
if (cbx1value != record.get('id') && cbx1value != record.get('id')) {
return true; // selected entry will be selected successfully
} else {
return false; // selected entry will not be selected
}
},
change: function ()
{
// Get the picker (list of items) of the other combobox and refresh it's template state
var cbx1picker = Ext.getCmp('combobox1').getPicker();
cbx1picker.refresh();
}
}
It's not the ultimate solution, but for one of my projects it worked like a charm. I have simplified the example as good as possible to make the solution clearer.
You will need two stores, one for each combo box, both filled with the same data.
And then you will do:
combo1.on('select',function(combo, newVal) {
combo2.getStore().filterBy(function(rec){
return rec.get("value")!=newVal;
})
});

Display issue with RowEditor and checkcolumn on ExtJS GridPanel

I'm using an ExtJS (v3.4.0) GridPanel with the RowEditor extension to allow users to add lines of text to a grid. I have also used the checkcolumn extension so users can check certain lines of text for later processing. So far, it looks like this:
However, when editing a row, the problem at hand becomes apparent:
The value underlying the checkcolumn is being displayed in text form along with the actual checkbox. I figured since users can check the checkboxes without editing the row, I would make this column uneditable to fix my issue. However, after modifying my code the true/false value is still being displayed in edit mode, the text value is just not editable anymore.
My code so far:
Ext.QuickTips.init();
var FreeText = Ext.data.Record.create([{
name: 'text',
type: 'string'
}, {
name: 'active',
type: 'bool'
}]);
var store = new Ext.data.GroupingStore({
reader: new Ext.data.JsonReader({fields: FreeText}),
sortInfo: {field: 'text', direction: 'ASC'}
});
var editor = new Ext.ux.grid.RowEditor({
saveText: 'Update'
});
var freeTextPanel = new Ext.grid.GridPanel({
store: store,
width: 600,
region:'center',
margins: '0 5 5 5',
autoExpandColumn: 'text',
plugins: [editor],
view: new Ext.grid.GroupingView({
markDirty: false
}),
tbar: [{
iconCls: 'icon-add',
text: 'Add',
handler: function(){
var e = new FreeText({
text: "",
active: true
});
editor.stopEditing();
store.insert(0, e);
freeTextPanel.getView().refresh();
freeTextPanel.getSelectionModel().selectRow(0);
editor.startEditing(0);
}
},{
ref: '../removeBtn',
iconCls: 'icon-delete',
text: 'Delete',
disabled: true,
handler: function(){
editor.stopEditing();
var s = freeTextPanel.getSelectionModel().getSelections();
for(var i = 0, r; r = s[i]; i++){
store.remove(r);
}
}
}, {
xtype: 'tbseparator'
}, {
iconCls: 'icon-excel-import',
//text: 'Import from CSV',
tooltip: 'Import CSV',
handler: function() {
alert( "Excel import here!" );
}
}],
columns: [
{
xtype: 'checkcolumn',
header: 'Active',
dataIndex: 'active',
align: 'center',
width: 50
}, {
id: 'text',
header: 'Free Text',
dataIndex: 'text',
width: 220,
sortable: true,
editor: {
xtype: 'textfield',
allowBlank: false
}
}],
isCellEditable: function(col, row) {
var record = store.getAt(row);
if (record.get('active')) {
return false;
}
return Ext.grid.ColumnModel.prototype.isCellEditable.call(this, col, row);
}
});
var layout = new Ext.Panel({
title: 'Free text entry',
layout: 'border',
layoutConfig: {
columns: 1
},
width:600,
height: 600,
items: [freeTextPanel]
});
layout.render(Ext.getBody());
freeTextPanel.getSelectionModel().on('selectionchange', function(sm){
freeTextPanel.removeBtn.setDisabled(sm.getCount() < 1);
});
Is there an easy way to simply get rid of the true/false text when editing a row?
Just in case, below are my RowEditor.js and CheckColumn.js files:
RowEditor.js
http://trac.geoext.org/browser/ext/3.4.0/examples/ux/RowEditor.js?rev=2740
CheckColumn.js
http://trac.geoext.org/browser/ext/3.4.0/examples/ux/CheckColumn.js?rev=2740
Turns out the solution to my problem was rather simple.
In the startEditing method of the RowEditor.js file I added the following code. I checked implicitly on the name of my item instead of for the checkbox type, in case I still need this functionality for other checkboxes later on:
for(var i = 0, len = cm.getColumnCount(); i < len; i++){
val = this.preEditValue(record, cm.getDataIndex(i));
if( cm.getDataIndex(i) == 'active' ) {
val = "";
}
f = fields[i];
f.setValue(val);
this.values[f.id] = Ext.isEmpty(val) ? '' : val;
}

How to achieve Live Search/Filtering on Multiple Fields in the Grid using Ext.Js?

I have done live search on grid. it is searching based on which column i mentioned filter code. But i need to filter grid records based on multiple column search. In below code only searches name column because mentioned only the name filed in filter code. I am not getting how to achieve multiple column value search? Can any one tell me how to achieve? great appreciated. Thank you .
Grid Code Here:
{
xtype: 'gridpanel',
flex: 2,
hidden: false,
store: store,
loadMask: true,
id: 'grid',
columns: [
{id:'id',header: 'ID', width: 100, sortable: true, dataIndex: 'id'},
{header: 'Name', width: 150, dataIndex: 'name'},
{header: 'Position', width: 150, dataIndex: 'position'},
{header: 'Ambition', width: 250, dataIndex: 'ambition'}
],
stripeRows: true,
title:'Straw Hats Crew',
},
liveSearch text change even Here:
onTextFieldChange: function(field, newValue, oldValue, options){
var grid = Ext.getCmp('grid');
if(newValue==''){
grid.store.clearFilter();
}
else {
grid.store.clearFilter();
grid.store.load().filter([
{id: 'name', property: "name", value: newValue, anyMatch: true}
]);
}
},
Something like this should work. You can specify an arbitrary filter function that can check all the fields in your model.
onTextFieldChange: function(field, newValue, oldValue, options){
var grid = Ext.getCmp('grid');
grid.store.clearFilter();
if (newValue) {
var matcher = new RegExp(Ext.String.escapeRegex(newValue), "i");
grid.store.filter({
filterFn: function(record) {
return matcher.test(record.get('id')) ||
matcher.test(record.get('name')) ||
matcher.test(record.get('position')) ||
matcher.test(record.get('ambition'));
}
});
}
}

In ExtJs 3.3.1, how can I show a ComboBox drop down without click in EditorGrid?

I am using ExtJs 3.3.1.
Within an EditorGrid, my "editable" column has a ComboBox as its editor. How can I have the ComboBox always showing for each row? Meaning, the user would not have to click on a cell to know there is a ComboBox there. Currently, I have clicksToEdit set to 1, but I wish I could set this to 0 (I tried that).
See some of my code below to see my current configuration.
var combo = new Ext.form.ComboBox({
typeAhead: true,
triggerAction: 'all',
lazyRender: true,
mode: 'local',
store: new Ext.data.ArrayStore({
id: 0,
fields: [
'statusId',
'displayText'],
data: data
}),
valueField: 'statusId',
displayField: 'displayText'
});
var cm = new Ext.grid.ColumnModel({
columns: [{
id: 'orderId',
header: 'ID',
dataIndex: 'id',
width: 50
}, {
header: 'Status',
dataIndex: 'status',
width: 130,
editor: (data.length == 1) ? null : combo,
renderer: Ext.util.Format.comboRenderer(combo)
}, {
id: 'orderSummary',
header: 'Summary',
dataIndex: 'summary',
renderer: this.renderSummary
}]
});
var orderGrid = new Ext.grid.EditorGridPanel({
store: this.getOrderStore(),
cm: cm,
autoExpandColumn: 'orderSummary',
clicksToEdit: 1
});
Here is the solution I came up with.
In my column model, I made sure that the column I am making "editable" has an id. Each cell in that column will now have a CSS class associated with it named "x-grid-col-{id}". My column id is "status" so the class was "x-grid-col-status".
I created the CSS for class "x-grid-col-status" which sets the dropdown arrow image as the background, aligned right. It also sets the cursor to pointer, so the user knows they can click on the cell.
.x-grid3-col-status
{
background-image: url(Image/trigger-single.gif);
background-position: right;
background-repeat: no-repeat;
cursor: pointer;
}
Next, I set up a listener for my ComboBox that listens for the 'focus' event. On focus, I expand the drop down. It is important that I had to add lazyInit: false to my ComboBox config, or else an empty list will appear when you expand. lazyInit - true to not initialize the list for this combo until the field is focused (defaults to true)
The code:
Ext.util.Format.comboRenderer = function (combo) {
return function (value, metaData, record, rowIndex, colIndex, store) {
var record = combo.findRecord(combo.valueField, value);
return record ? record.get(combo.displayField) : combo.valueNotFoundText;
}
}
var combo = new Ext.form.ComboBox({
typeAhead: true,
triggerAction: 'all',
lazyInit: false,
lazyRender: true,
mode: 'local',
editable: false,
store: new Ext.data.ArrayStore({
id: 0,
fields: [
'statusId',
'displayText'
],
data: data
}),
valueField: 'statusId',
displayField: 'displayText',
listeners: {
'focus': {
fn: function (comboField) {
comboField.doQuery(comboField.allQuery, true);
comboField.expand();
}
, scope: this
}
, 'select': {
fn: function (comboField, record, index) {
comboField.fireEvent('blur');
}
, scope: this
}
}
});
var cm = new Ext.grid.ColumnModel({
defaults: {
sortable: true
},
columns: [
{
id: 'orderId',
header: 'ID',
dataIndex: 'id',
width: 50
}, {
header: 'Status',
id: 'status',
dataIndex: 'status',
width: comboColumnWidth,
editor: combo,
renderer: Ext.util.Format.comboRenderer(combo)
}, {
id: 'orderSummary',
header: 'Summary',
dataIndex: 'summary',
renderer: this.renderSummary
}
]
});
var orderGrid = new Ext.grid.EditorGridPanel({
store: this.getOrderStore(),
cm: cm,
autoExpandColumn: 'orderSummary',
title: title,
clicksToEdit: 1
});
I think you'll need to add a special css to the combo box that displays the drop down icon. This is natively not supported by Ext JS. Here's an example of how it can be done:
var companyColumn = {
header: 'Company Name',
dataIndex: 'company',
renderer: function(value, metaData, record, rowIndex, colIndex, store) {
// provide the logic depending on business rules
// name of your own choosing to manipulate the cell depending upon
// the data in the underlying Record object.
if (value == 'whatever') {
//metaData.css : String : A CSS class name to add to the TD element of the cell.
//metaData.attr : String : An html attribute definition string to apply to
// the data container element within the table
// cell (e.g. 'style="color:red;"').
metaData.css = 'name-of-css-class-you-will-define';
}
return value;
}
}
Or you could use the Ext.grid.TemplateColumn and specify the tpl config. This will automatically generate a renderer for the cells in the column and apply the tpl.

Resources