I have a web app that I am working on that uses ExtJS 6.5.2 and I have setup a grid panel with the row expander plugin. Inside that row expander I attach a widget a 'rowwidget' that contains another grid panel or a nested grid. What I am trying to do is use the gridviewdragdrop plugin in extjs to be able to drag records in and out of the nested grids and the parent grid. The parent grid (the one with the row expander) has a locked section so I actually have two grids when I expand the row one on the locked side and one on the non locked part. Both of these nested grids though have the same store loaded to them and the data displayed on each side is the same record just different fields from the model are shown in each. Here is a screenshot with the row expander open for context: Screenshot of Grids
Here is my parent grid definition:
Ext.define('myefiles.jobs.pdd.view.main.cardpanel.equipmentList.EquipmentList', {
extend: 'Ext.grid.Panel',
requires: ['myefiles.jobs.pdd.view.main.cardpanel.equipmentList.EquipmentListController',
'myefiles.jobs.pdd.view.main.cardpanel.equipmentList.NestedEquipmentListGrid',
'myefiles.jobs.pdd.view.main.cardpanel.equipmentList.NestedEquipmentListLockedGrid'],
controller: {
xclass: 'myefiles.jobs.pdd.view.main.cardpanel.equipmentList.EquipmentListController'
},
session: true,
title: 'Equipment List',
itemId: 'equipmentListGrid',
reference: 'equipmentListGrid',
plugins: [{
ptype: 'gridfilters',
},
{
ptype: 'rowwidget',
id: 'nestedGridRowWidget',
widget: {xclass: 'myefiles.jobs.pdd.view.main.cardpanel.equipmentList.NestedEquipmentListGrid'},
lockedWidget:{xclass: 'myefiles.jobs.pdd.view.main.cardpanel.equipmentList.NestedEquipmentListLockedGrid'},
selectRowOnExpand: false,
expandOnDblClick: false,
expandOnEnter: false,
onWidgetAttach: function(plugin, grid, record) {
grid.setConfig('record', record);
},
}],
listeners: {
select: function(sel, record, index, eOpts) {
var nestedLockedGrid = Ext.ComponentQuery.query('#nestedEquipmentListLockedGrid');
var nestedGrid = Ext.ComponentQuery.query('#nestedEquipmentListGrid');
for(let i = 0; i < nestedGrid.length; i++) {
nestedGrid[i].getSelectionModel().deselectAll();
nestedLockedGrid[i].getSelectionModel().deselectAll();
}
this.lookupViewModel().set('hasSelection', true);
}
},
viewModel: {
data: {
hasSelection: false
}
},
viewConfig: {
plugins: {
gridviewdragdrop: {
dragText: 'Test',
}
},
listeners: {
drop: function(node, data, dropRec, dropPosition) {
var dropOn = dropRec ? ' ' + dropPosition + ' ' + dropRec.get('name') : ' on empty view';
}
},
preserveScrollOnRefresh: true,
preserveScrollOnReload: true,
//getRowClass: function
},
tbar: [{
xtype: 'storesearch',
bind: {
store: '{equipmentList}'
},
fields: ['equipmentID', 'tagType', 'tagNumber', 'job', 'division', 'poNo', 'mroNo', 'qty', 'equipmentDesc', 'drawingNumber',
'skidNumber', 'area', 'products', 'equipmentType', 'connSize', 'addInfo', 'serialNo', 'hp', 'volt', 'vendorName', 'contactName',
'manufacturer', 'modelNumber', 'mroBy', 'mroDescription', 'symbolic', 'costcode', 'gmpCost', 'mroCost', 'option', 'POID', 'poNo', 'mroNo']
}, {
text: 'Add Record',
handler: 'onAdd',
bind: {
hidden: '{pdd.isReadOnlyUser}'
}
}, {
text: 'Edit Record',
handler: 'onEdit',
bind: {
disabled: '{!hasSelection}',
hidden: '{pdd.isReadOnlyUser}'
}
}, {
text: 'Duplicate Record',
handler: 'onDup',
bind: {
disabled: '{!hasSelection}',
hidden: '{pdd.isReadOnlyUser}'
}
}, {
xtype: 'splitbutton',
text: 'Excel Options',
menu: [{
text: 'Upload From Excel File',
handler: 'onUpload'
}, {
text: 'Download Excel Templates',
handler: 'onTemplate'
}, {
text: 'Download Current Equipment List',
handler: 'onDownloadEq'
},{
text: 'Download Current Equipment List for Customer',
handler: 'onDownloadPID'
}],
bind: {
hidden: '{pdd.isReadOnlyUser}'
}
}, {
xtype: 'splitbutton',
text: 'Lot Options',
menu: [{
text: 'Add Lot',
handler: 'onAddLot'
}, {
text: 'Delete Lot',
handler: ''
}],
bind: {
hidden: '{pdd.isReadOnlyUser}'
}
}, '->', {
text: 'Delete Record',
handler: 'onDelete',
bind: {
disabled: '{!hasSelection}',
hidden: '{pdd.isReadOnlyUser}'
}
}],
// columns property: array of configuration objects or just configuration object
columns: [{
header: '*EquipmentID',
dataIndex: 'equipmentID',
filter: 'number',
width: 105,
locked: true
}, {
header: '*JobNo',
dataIndex: 'job',
filter: 'number',
width: 65,
locked: true
}, {
header: '*Div',
dataIndex: 'division',
filter: 'string',
width: 50,
locked: true
}, {
header: '*TType',
dataIndex: 'tagType',
filter: 'string',
width: 65,
locked: true
}, {
header: '*TNo',
dataIndex: 'tagNumber',
filter: 'string',
width: 90,
locked: true
}, {
header: 'QTY',
dataIndex: 'qty',
filter: 'number',
width: 50
}, {
header: 'Equipment Desc',
dataIndex: 'equipmentDesc',
width: 220,
filter: 'string'
}, {
header: 'Drawing_Number',
dataIndex: 'drawingNumber',
filter: 'string',
width: 130
}, {
header: 'Skid_Number',
dataIndex: 'skidNumber',
filter: 'string',
width: 100
}, {
header: 'Area',
dataIndex: 'area',
filter: 'string',
width: 125,
}, {
header: 'Products',
dataIndex: 'products',
filter: 'string',
width: 110
}, {
header: 'Equipment Type',
dataIndex: 'equipmentType',
filter: 'string',
width: 200,
}, {
header: 'ConnSize',
dataIndex: 'connSize',
filter: 'string',
width: 80
}, {
header: 'Add Info',
dataIndex: 'addInfo',
filter: 'string',
width: 75
}, {
header: 'Serial No',
dataIndex: 'serialNo',
filter: 'string',
width: 75
}, {
header: 'Hp',
dataIndex: 'hp',
filter: 'string',
width: 45,
},{
header: 'Volt',
dataIndex: 'volt',
filter: 'string',
width: 45
},{
header: 'Vendor',
dataIndex: 'vendorName',
filter: 'string',
width: 275
}, {
header: 'Contact',
dataIndex: 'contactName',
filter: 'string',
width: 125
}, {
header: 'Manufacturer',
dataIndex: 'manufacturer',
filter: 'string',
width: 100
}, {
header: 'Model No',
dataIndex: 'modelNumber',
filter: 'string',
width: 100
}, {
header: 'MRO By',
dataIndex: 'mroBy',
filter: 'string',
width: 150
}, {
header: 'MRODescription',
dataIndex: 'mroDescription',
filter: 'string',
width: 500
}, {
header: 'Symbolic',
dataIndex: 'symbolic',
filter: 'string',
width: 100
}, {
header: 'Cost Code',
dataIndex: 'costcode',
filter: 'number',
width: 85
}, {
header: 'GMPCost',
dataIndex: 'gmpCost',
xtype: 'numbercolumn',
format: '$0,000.00',
filter: 'number',
width: 80,
bind: {
hidden: '{pdd.isReadOnlyUser}'
}
}, {
header: 'MROCost',
xtype: 'numbercolumn',
format: '$0,000.00',
dataIndex: 'mroCost',
filter: 'number',
width: 100,
bind: {
hidden: '{pdd.isReadOnlyUser}'
}
}, {
header: 'Option',
dataIndex: 'option',
filter: 'string',
width: 60
}, {
header: 'POID',
dataIndex: 'POID',
filter: 'number',
width: 60
}, {
header: '*PONo',
dataIndex: 'poNo',
filter: 'string',
width: 65
}, {
header: '*MRONo',
dataIndex: 'mroNo',
filter: 'string',
width: 200
}, {
header: 'MRO PDF',
xtype: 'templatecolumn',
width: 85,
tpl: '<tpl if="POID != 0"> <a href="/auth/jasper?reportUnit=/reports/myefiles_pdd/EquipmentMRO&type=pdf&POID={POID}&location=/reports/myefiles_pdd/" target=_blank>PDF</a> </tpl>',
bind: {
hidden: '{pdd.isReadOnlyUser}'
}
}],
selModel: {selType: 'rowmodel', mode: 'MULTI'},
// bbar: {
// xtype: 'pagingtoolbar',
// displayInfo: true
// }
});
Here is my nested Grid definition:
Ext.define('myefiles.jobs.pdd.view.main.cardpanel.equipmentList.NestedEquipmentListGrid',{
extend: 'Ext.grid.Panel',
itemId: 'nestedEquipmentListGrid',
width: 2000,
style: 'border: solid Black 1px',
config: {
record: null
},
listeners: {
select: function(sel, record, index, eOpts) {
var me = this;
var nestedLockedGrid = Ext.ComponentQuery.query('#nestedEquipmentListLockedGrid'); //arrray of all nested locked grids.
var nestedGrid = Ext.ComponentQuery.query('#nestedEquipmentListGrid'); //array of all nestedGrids
var parentGrid = Ext.ComponentQuery.query('#equipmentListGrid'); //array of only the parent grid since there is only one.
//loop through arrays of nested grids and deselect if it is not the same grid as the one selected on.
for(let i = 0; i < nestedGrid.length; i++) {
if(nestedGrid[i] != me) {
nestedGrid[i].getSelectionModel().deselectAll();
nestedLockedGrid[i].getSelectionModel().deselectAll();
} else {
nestedLockedGrid[i].getSelectionModel().select(index);
}
}
parentGrid[0].getSelectionModel().deselectAll();
parentGrid[0].lookupViewModel().set('hasSelection', true);
},
},
viewConfig: {
plugins: {
gridviewdragdrop: {
dragText: 'Test',
//dragGroup: 'secondGridDDGroup',
//dropGroup: 'firstGridDDGroup'
}
},
},
columns: [
{
header: 'QTY',
dataIndex: 'qty',
filter: 'number',
width: '5%'
}, {
header: 'Equipment Desc',
dataIndex: 'equipmentDesc',
width: '10%',
filter: 'string'
}, {
header: 'Drawing_Number',
dataIndex: 'drawingNumber',
filter: 'string',
width: '10%'
}, {
header: 'Skid_Number',
dataIndex: 'skidNumber',
filter: 'string',
width: '10%'
}, {
header: 'Area',
dataIndex: 'area',
filter: 'string',
width: '5%'
}, {
header: 'Products',
dataIndex: 'products',
filter: 'string',
width: '5%'
}, {
header: 'Equipment Type',
dataIndex: 'equipmentType',
filter: 'string',
width: '10%'
}, {
header: 'ConnSize',
dataIndex: 'connSize',
filter: 'string',
width: '5%'
}, {
header: 'Add Info',
dataIndex: 'addInfo',
//maxWidth: 500,
filter: 'string',
width: '10%'
}, {
header: 'Serial No',
dataIndex: 'serialNo',
filter: 'string',
width: '10%'
}, {
header: 'Hp',
dataIndex: 'hp',
filter: 'string',
width: '5%'
},{
header: 'Volt',
dataIndex: 'volt',
filter: 'string',
width: '5%'
},
/*
{
header: 'Vendor',
dataIndex: 'vendorName',
filter: 'string',
width: 275
},
{
header: 'Contact',
dataIndex: 'contactName',
filter: 'string',
width: 125
},
*/
{
header: 'Manufacturer',
dataIndex: 'manufacturer',
filter: 'string',
width: '5%'
},
{
header: 'Model No',
dataIndex: 'modelNumber',
filter: 'string',
width: '5%'
},
/**
{
header: 'MRO By',
dataIndex: 'mroBy',
filter: 'string',
width: 150
}, {
header: 'MRODescription',
dataIndex: 'mroDescription',
filter: 'string',
width: 500
}, {
header: 'Symbolic',
dataIndex: 'symbolic',
filter: 'string',
width: 100
}, {
header: 'Cost Code',
dataIndex: 'costcode',
filter: 'number',
width: 85
}, {
header: 'GMPCost',
dataIndex: 'gmpCost',
xtype: 'numbercolumn',
format: '$0,000.00',
filter: 'number',
width: 80,
bind: {
hidden: '{pdd.isReadOnlyUser}'
}
}, {
header: 'MROCost',
xtype: 'numbercolumn',
format: '$0,000.00',
dataIndex: 'mroCost',
filter: 'number',
width: 100,
bind: {
hidden: '{pdd.isReadOnlyUser}'
}
}, {
header: 'Option',
dataIndex: 'option',
filter: 'string',
width: 60
}, {
header: 'POID',
dataIndex: 'POID',
filter: 'number',
width: 60
}, {
header: '*PONo',
dataIndex: 'poNo',
filter: 'string',
width: 65
}, {
header: '*MRONo',
dataIndex: 'mroNo',
filter: 'string',
width: 200
}, {
header: 'MRO PDF',
xtype: 'templatecolumn',
width: 85,
tpl: '<tpl if="POID != 0"> <a href="/auth/jasper?reportUnit=/reports/myefiles_pdd/EquipmentMRO&type=pdf&POID={POID}&location=/reports/myefiles_pdd/" target=_blank>PDF</a> </tpl>',
bind: {
hidden: '{pdd.isReadOnlyUser}'
}
}
*/],
selModel: {selType: 'rowmodel', mode: 'MULTI'}
});
Here is my nested Locked Grid definition:
Ext.define('myefiles.jobs.pdd.view.main.cardpanel.equipmentList.NestedEquipmentListLockedGrid',{
extend: 'Ext.grid.Panel',
itemId: 'nestedEquipmentListLockedGrid',
style: 'border: solid Black 1px',
config: {
record: null
},
listeners: {
//make sure both nested grids select the same item and the parent grids deselct if something is selected in a nested grid this way
//add record edit record etc can find the sole record that is selected.
select: function(sel, record, index, eOpts) {
var me = this;
var nestedLockedGrid = Ext.ComponentQuery.query('#nestedEquipmentListLockedGrid'); //arrray of all nested locked grids.
var nestedGrid = Ext.ComponentQuery.query('#nestedEquipmentListGrid'); //array of all nestedGrids
var parentGrid = Ext.ComponentQuery.query('#equipmentListGrid'); //array of only the parent grid since there is only one.
//loop through arrays of nested grids and deselect if it is not the same grid as the one selected on.
for(let i = 0; i < nestedLockedGrid.length; i++) {
if(nestedLockedGrid[i] != me) {
nestedGrid[i].getSelectionModel().deselectAll();
nestedLockedGrid[i].getSelectionModel().deselectAll();
} else {
nestedGrid[i].getSelectionModel().select(index);
}
}
parentGrid[0].getSelectionModel().deselectAll();
parentGrid[0].lookupViewModel().set('hasSelection', true);
},
beforerender: function(){
var me = this;
var selectedRecord = me.record;
var nestedGrid = Ext.ComponentQuery.query('#nestedEquipmentListGrid');
/**
var nestedLockedGrid = Ext.ComponentQuery.query('#nestedEquipmentListLockedGrid');
nestedGrid[nestedGrid.length-1].getEl().swallowEvent([
'focusenter'
]);
nestedLockedGrid[nestedLockedGrid.length-1].getEl().swallowEvent([
'focusenter'
]);
*/
//create the store and then filter it based off the lotid of the record its attached too:
var nestedStore = Ext.create('myefiles.jobs.pdd.view.main.cardpanel.equipmentList.NestedEquipmentListGridStore', {
storeID: 'tableData',
});
nestedStore.filterBy(function(record) {
if(record.get('lotItem') == 1 && record.get('lotID') == selectedRecord.get('lotID'))
return true;
});
if(selectedRecord.get('lotID') != 0) {
me.setStore(nestedStore);
nestedGrid[nestedGrid.length - 1].setStore(nestedStore);
} else {
me.setHidden(true);
nestedGrid[nestedGrid.length - 1].setHidden(true);
}
}
},
viewConfig: {
plugins: {
gridviewdragdrop: {
dragText: 'Test',
//dragGroup: 'secondGridDDGroup',
//dropGroup: 'firstGridDDGroup'
}
},
},
columns: [{
header: '*EquipmentID',
dataIndex: 'equipmentID',
filter: 'number',
width: '20%'//105,
//locked: true
},
{
header: '*JobNo',
dataIndex: 'job',
filter: 'number',
width: '20%'//65,
//locked: true
},
{
header: '*Div',
dataIndex: 'division',
filter: 'string',
width: '20%'//50,
//locked: true
},
{
header: '*TType',
dataIndex: 'tagType',
filter: 'string',
width: '20%'//65,
//locked: true
}, {
header: '*TNo',
dataIndex: 'tagNumber',
filter: 'string',
width: '20%'//90,
//locked: true
}],
selModel: {selType: 'rowmodel', mode: 'MULTI'},
});
You'll notice I have the 'gridviewdragdrop' plugin on my viewConfig for all 3 grids I am able to drag a record and move it from one spot to another inside the parent grid but anytime I try to drag or move anything inside of the nested grids it will not move even inside of the nested grid or in and out of it. I get this error in my dev tools console when trying to do so: Screenshot of Error I've done a bit of looking around on google and I'm still pretty novice to web development and extjs but I read on another post that was doing something a little different than mine but getting a similar error that this is because the event is fired in the context of the parent grid. Is there any way I can override something or somehow get this to work?
I apologize for the messy code I have been tinkering around with this for a bit and so there are commented out code sections in places. I hope I provided enough context if more is needed let me know and I appreciate any help thank you.