ExtJS - Drag column header to other grid - extjs

I need keep the default feature of reordering columns and add
possibility drop the column in a second grid, building in the last a list
with the columns of first grid.
I hope has been clear.

I solved the issue extending DropZone. This implementation receive as constructor param the target grid, and this, be in the rbar (docked control) of source grid. The key is set ddGroup to "header-dd-zone-" plus id from source grid. I hope this is useful.
Ext.define('Crud.FilterDropZone', {
extend: 'Ext.dd.DropZone'
, constructor: function() {}
, init: function (grid) {
var me = this;
if (grid.rendered) {
me.grid = grid;
me.ddGroup = 'header-dd-zone-' + grid.up('grid').id;
grid.getView().on({
render: function(v) {
me.view = v;
Crud.FilterDropZone.superclass.constructor.call(me, me.view.el);
},
single: true
});
} else {
grid.on('render', me.init, me, {single: true});
}
}
, getTargetFromEvent: function (e) {
return {};
}
, onNodeDrop: function (nodeData, source, e, data) {
var header = data.header
, store = Ext.getCmp(e.target.id).getStore();
//store.add(new store.RecordType({ property: header.text, value: '', reference: header.dataIndex}));
store.add([[header.text, '', header.dataIndex]]);
}
});

Related

Shopware - Extjs - How to get value of the table element?

For some time I have a problem with my Shopware plugin. I extended article listWindow, added a column with checkbox. When customer clicks on checkbox I need to get article number that is in another column.
The way I first did it seems unreliable because it depends on position of a columns that can change.
//{block name="backend/article_list/view/main/grid"}
//{$smarty.block.parent}
//{namespace name=backend/article_list/main}
Ext.define('Shopware.apps.ArticleList.view.main.etsy_attribute.Grid', {
override: 'Shopware.apps.ArticleList.view.main.Grid',
...
getToolbar: function () {
var me = this, buttons;
buttons = me.callParent();
me.equaliseEtsyBtn = Ext.create('Ext.button.Button', {
text: 'Etsy equalise',
iconCls: 'sprite-drive-upload',
onClick: function () {
var i,
recPerPage = me.items.items[0].all.elements,
for (i = 0; i < recPerPage.length; i++) {
var productNumber = recPerPage[i].children[2].innerText;
if( recPerPage[i].children[numOfChildren].children[0].children[0].checked === true) {
Ext.Ajax.request({
method: 'POST',
url: '{url controller="someController" action="someAction"}',
params: Object.assign({
productNumber: productNumber
}),
success: function (res) {
//var parsed = JSON.parse(res.responseText);
},
failure: function () {
}
});
} else {
});
}
}
}
});
buttons.add(me.equaliseEtsyBtn);
return buttons;
},
})
What is bad here is this:
recPerPage[i].children[numOfChildren].children[0].children[0].checked === true
And similar lines. How to get value I need in some smarter and more accurate way?
Alse tried with .down and .up
Please give me some direction!

How to remove the summary grouping of particular row in EXTJS

If I apply groupField property in the grid and store, extjs will automatically sort records by groupField.
For example: http://dev.sencha.com/deploy/ext-4.0.0/examples/grid/group-summary-grid.html, it used 'project' as groupField.
My Question is How can I add an extra row, which does not belong to any group, into a grid with groupField. (Like this: http://i59.tinypic.com/30s973l.jpg)
By default group is made for each value from groupField, also for empty groupField (but it appears first). If it is enough for you then you don't have to do anything.
Fiddle: http://jsfiddle.net/tme462tj/
When you want to have behavior like on attached image, then some work has to be done.
To put empty value at the end, you can create convert function for model field (eg: convert: function(v) { return v ? v : defaultDepartment; }). If you want to hide header and summary for this empty group, you can attach event listener to viewready event and hide them using styles:
viewready: function() {
var els = this.getEl().query('.x-grid-group-hd');
els = Ext.Array.filter(els, function(e) { return e.textContent.trim() == defaultDepartment; });
if (els.length !== 1) {
return;
}
var header = Ext.fly(els[0]);
header.setStyle('display', 'none');
var summary = header.up('.x-group-hd-container').down('.x-grid-row-summary');
if (summary) {
summary.setStyle('display', 'none');
}
}
Fiddle: http://jsfiddle.net/hdyokgnx/1/
As per my comment on the accepted solution, this revision makes the grouping header hide permanently for the duration of that grid view.
This solves my problem of needing a grouping grid but with one group that does not have a group header row.
store.load
({
params :
{
arg1 : 1
,arg2 : '2'
}
,callback : function( records, operation, success )
{
var els = me.theGrid.getEl().query('.x-grid-group-hd');
els = Ext.Array.filter( els, function(e)
{
return e.textContent.trim().includes( "*** A SUBSTRING IN GROUPING FIELD ***" );
});
if (els.length !== 1)
{
return;
}
var header = Ext.fly(els[0]);
header.setStyle('display', 'none');
var summary = header.up('.x-group-hd-container').down('.x-grid-row-summary');
if (summary)
{
summary.setStyle('display', 'none');
}
}
});

Cannot read property 'superclass' of undefined / Object #<Object> has no method 'addCls'

--------------------- Solution ---------------------------
I did a workaround of having to callParent inside my code,
var expandFieldOverride = function(event)
{
//event: collapse, false / expand, true
var fieldset = this;
var arguments = [event];
if(!fieldset.readyToExpand){
Ext.each(profilesPanel.items.items, function(panel, i)
{
if (panel.isProfilePanel)
{
console.log(event);
var field = panel.down('profileform[title=Standard Configuration]').down('fieldset[name='+fieldset.name+']');
field.readyToExpand = true;
field.setExpanded(event);
}
});
}
this.callParent(arguments);
fieldset.readyToExpand = false;
}
-------------------------Initial Problem-------------------------------
I am using ExtJS 4.2.1 and I am trying to override the collapse and expand events of fieldsets. Using collapse and expand didn't work, so I had to directly override setExpanded(). I am trying to achieve the event that when one fieldset is collapsed in a profile panel, so is the other in the other profile panel, and vice versa.
Ext.define('EcoCentral.Configuration.ThermostatProfiles.ProfileOptionsFieldSet',
{
extend: 'Ext.form.FieldSet',
setExpanded: expandFieldOverride,
//expand: expandFieldOverride,
//collapse: collapseFieldOverride,
alias: 'widget.profilefieldset'
});
var expandFieldOverride = function(event)
{
//this.callParent(arguments);
//event: collapse, false / expand, true
var fieldset = this;
var arguments = [event];
Ext.each(profilesPanel.items.items, function(panel, i)
{
if (panel.isProfilePanel)
{
var field = panel.down('profileform[title=Standard Configuration]').down('fieldset[name='+fieldset.name+']');
console.log(field);
//field.callParent(arguments);
field.self.superclass.setExpanded.call(arguments);
}
//this.callParent(arguments);
});
}
If I use 'this.callParent(arguments)' inside the code, I recieve
'Uncaught TypeError: Cannot read property 'superclass' of undefined '
I did some research and tried out this line of code
'field.self.superclass.setExpanded.call(arguments);'
from which I recieve :
'Uncaught TypeError: Object # has no method 'addCls''
Which is a call inside of the setExpanded function in the source.
setExpanded: function(expanded) {
var me = this,
checkboxCmp = me.checkboxCmp,
operation = expanded ? 'expand' : 'collapse';
if (!me.rendered || me.fireEvent('before' + operation, me) !== false) {
expanded = !!expanded;
if (checkboxCmp) {
checkboxCmp.setValue(expanded);
}
if (expanded) {
me.removeCls(me.baseCls + '-collapsed');
} else {
me.addCls(me.baseCls + '-collapsed');
}
me.collapsed = !expanded;
if (expanded) {
delete me.getHierarchyState().collapsed;
} else {
me.getHierarchyState().collapsed = true;
}
if (me.rendered) {
// say explicitly we are not root because when we have a fixed/configured height
// our ownerLayout would say we are root and so would not have it's height
// updated since it's not included in the layout cycle
me.updateLayout({ isRoot: false });
me.fireEvent(operation, me);
}
}
return me;
},
My fieldset is defined by xtype:
You have to use apply. Call is the wrong function. Have a look at this:
What is the difference between call and apply?

ext js drag drop dataview determine node dropped on

I am using ext js to drag and drop data from one dataview to another. I want to know if the drop event happened on top of an existing node or if it was just dropped in the white space of the dataview.
Here's the code for my dropTarget:
...
onDesktopDataViewRender: function (v) {
var dataView = v;
v.dropTarget = Ext.create('Ext.dd.DropTarget', v.el, {
ddGroup: 'FromSearchToDesktop',
notifyDrop: function (source, e, dropData) {
//Want do do something like:
//if(dropped directly on any node) {
// do some logic with that node
//}
//else {
// do the code below
var recordAlreadyExists = false;
v.store.each(function (r) {
if (r.data.ID == dropData.searchData.ID) {
recordAlreadyExists = true;
}
});
if (recordAlreadyExists == false) {
v.store.add(dropData.searchData);
}
//end else
}
});
}
...
Yay! Finally figured this one out.
The quick answer is to create a DropZone for the node. The long answer is how to do that.
In my program, the user can drag items from DataView A to DataView B. After dropping the item in DataView B, the item appears in DataView B. On top of that, the user can drag an item from DataView A, and drop it on a node inside DataView B. The code needs to differentiate between the item being dropped on the DataView and the item being dropped on a node inside the DataView.
Generic instructions:
In DataViewB's onrender event, create a dropTarget with a ddGroup of
"DataViewB"
Inside the notifyDrop function, create a new node.
Also inside the notifyDrop function, create another dropTarget
(this one for the node instead of the DataView) with a ddGroup of "DataViewBNode".
Inside DataViewA's onRender event, create a DragZone with a ddGroup
of "DataViewBNode" (!important!)
Inside of DataViewA's afterrender event, add the dragZone to the
"DataViewB" group.
Now you will be able to drag from DataViewA and drop in the white space of DataViewB to add a node, but you will also be able to drop directly on a node from DataViewB and do a different action.
It's very important that the first ddGroup is for the node, and the one that's added in the afterrender event is for the DataView
Here is the code for DataView A:
onDataViewARender: function (v) {
var dataView = v;
...
v.dragZone = Ext.create('Ext.dd.DragZone', v.getEl(), {
ddGroup: 'DataViewBNode',
getDragData: function (e) {
var sourceEl = e.getTarget(v.itemSelector, 10), d;
if (sourceEl) {
d = sourceEl.cloneNode(true);
d.id = Ext.id();
return v.dragData = {
sourceEl: sourceEl,
repairXY: Ext.fly(sourceEl).getXY(),
ddel: d,
searchData: v.getRecord(sourceEl).data,
store: v.store,
source: 'DataViewA'
}
}
},
getRepairXY: function () {
return this.dragData.repairXY;
}
});
},
onDataViewAAfterRender: function(v) {
var dragZone = v.dragZone;
dragZone.addToGroup('DataViewB');
},
Here is the code for DataViewB
onDataViewBRender: function (v) {
var dataView = v;
v.dropTarget = Ext.create('Ext.dd.DropTarget', v.el, {
ddGroup: 'DataViewB',
notifyDrop: function (source, e, dropData) {
var recordAlreadyExists = false;
v.store.each(function (r) {
if (r.data.ID == dropData.searchData.ID && r.data.Type == dropData.searchData.Type) {
recordAlreadyExists = true;
}
});
if (recordAlreadyExists == false) {
v.store.add(dropData.searchData);
var nodes = v.container.dom.childNodes[0].childNodes;
var index = v.container.dom.childNodes[0].childNodes.length -1;
//
//Here is where you create the dropTarget for the new node
//
nodes[index].dropTarget = Ext.create('Ext.dd.DropTarget', nodes[index], {
ddGroup: 'DataViewBNode',
notifyDrop: function (source, e, dropData) {
console.log('success')
}
});
}
}
});
...
},

EXTJS 3.3.3 Grid

I am developing a checkbox grid list with pagination using the EXTJS grid. I need to remember the selected record when the page navigation is performed.
Details:
1) Go to page:1 and selected rows 1,2 and 3.
2) Now navigate to page:2
3) Come back to page:1
4) The rows 1,2 and 3 which are already selected should be shown as selected
Is there is any api in grid which handles this kind of function?
Thanks in advance.
Thanks for your responses. I have achieved my design by implementind a plugin for grid. The plugin looks as,
Ext.namespace('Ext.ux.plugins');
Ext.ux.plugins.CheckBoxMemory = Ext.extend(Object,
{
constructor: function(config)
{
if (!config)
config = {};
this.prefix = 'id_';
this.items = {};
this.idProperty = config.idProperty || 'id';
},
init: function(grid)
{
this.view = grid.getView()
this.store = grid.getStore();
this.sm = grid.getSelectionModel();
this.sm.on('rowselect', this.onSelect, this);
this.sm.on('rowdeselect', this.onDeselect, this);
this.store.on('clear', this.onClear, this);
this.view.on('refresh', this.restoreState, this);
},
onSelect: function(sm, idx, rec)
{
this.items[this.getId(rec)] = true;
},
onDeselect: function(sm, idx, rec)
{
delete this.items[this.getId(rec)];
},
restoreState: function()
{
var i = 0;
var sel = [];
this.store.each(function(rec)
{
var id = this.getId(rec);
if (this.items[id] === true)
sel.push(i);
++i;
}, this);
if (sel.length > 0)
this.sm.selectRows(sel);
},
onClear: function()
{
var sel = [];
this.items = {};
},
getId: function(rec)
{
return rec.get(this.idProperty);
}
});
This plugin was called from gird as,
Ext.grid.Gridpanel({
store: 'someStore',
plugins: [new Ext.ux.plugins.CheckBoxMemory({idProperty: "recordID"})]
});
Hope this helps some one.
I don't think there is. You;d need to store IDs of selected records in some separate store/array and use it to re-apply selections when page is changed.
You could put a MixedCollection Object at the global scope to keep track of these records. This will allow you to store global settings of different object types.

Resources