ExtJS extend grid RowEditor plugin (to edit array) - extjs

I've been using the ExtJS grid row editing plugin pretty liberally for CRUD operations in web applications. Now, I have a requirement to allow a database record to be edited along with a related collection/array (from another datastore) using this row editing plugin.
To do this I want to insert drag-n-drop grids inside of a row that has been selected for editing, one grid showing the available (unused) collection items on the left and another grid to hold the defined collection items on the right.
To illustrate what I am trying to do, here is the normal row editing plugin with a row selected for editing:
I am trying to do this (drag-n-drop grids inside of row editor div):
To do this I have been trying to simply run something like Ext.getCmp(???).add(myDnDGridPanel); but I haven't found the right thing to attach this to (what to put in the question marks).
It seems reasonable enough to use this plugin to edit the related collection/array along with the database record. Does anyone know a simple way to add items to this row editor div?
Or... will I have to hack/extend the plugin to accomplish this?

Below is example RowEditing plugin modification which allows to add additional components. In this demo this is only a button, but it should be easy to customize.
var rowEditing = Ext.create('Ext.grid.plugin.RowEditing', {
clicksToMoveEditor: 1,
autoCancel: false,
listeners: {
beforeedit: function(editor, e, eOpts) {
var body = this.editor.body;
var container = body.down('.container-for-extra-content');
if (!container) {
container = Ext.core.DomHelper.insertAfter(body.last(), '<div class="container-for-extra-content"></div>', true);
container.setWidth(this.editor.body.getWidth(true));
container.setHeight(this.extraHeight);
this.editor.getEl().setHeight(this.editor.getEl().getHeight() + this.extraHeight);
this.editor.body.setHeight(this.editor.body.getHeight() + this.extraHeight);
var panelConfig = {
renderTo: container,
items: [this.extraComponent]
};
Ext.create('Ext.Panel', panelConfig);
}
},
delay: 1
},
extraHeight: 100,
extraComponent: {
xtype: 'panel',
items: [
{ xtype: 'button', text: 'Aloha!' }
]
}
});
Here is working sample: http://jsfiddle.net/e2DzY/1/

Related

In ExtJs 6.2, a column that contains an item does not take into account its flex property, is there a workaround?

In ExtJs 6.2, there is a bug described here in the Sencha Forum.
Since 6.2+ Ext.grid.Panel ignores flex when using column items.
Steps to reproduce the problem: Create a grid in fiddle with 6.2+ Add
columns without items and flex:1 klick run in fiddle and it looks just
fine Add a item to the column with flex:1 klick again run in fiddle an
flex wil get ignored!
The result that was expected: I would expect the column to flex.
The result that occurs instead: The column will render in the minimum
size.
The thread says this be corrected in the nightly build, but ExtJs 6.2.1 is not yet available in the GPL version. Is there a workaround for this issue ?
Or would id be possible for someone to publish an override with the bugfix ?
Edit: Additional insight
Looking at the events bound to the columns and the grid I can assert that the bug is happening between the afterrender event (column.flex = 1) and the afterlayout event (column.flex = null). I don't know much of the layout run details of ExtJs, so I'm short of ideas on how to further narrow down where the offending code might be locaded. If anyone can give hints in this direction instead of a complete answer, they are also welcome.
I found as a workaround to resize the columns once the grid is laid out. This works as it should.
The only drawback is that it lays out the columns twice.
Ext.define('App.override.grid.Panel', {
override: 'Ext.grid.Panel',
initComponent: function() {
this.callParent(arguments);
this.on('afterlayout', this.resizeColumns);
},
resizeColumns: function () {
var me = this,
width = this.getWidth(),
flex = 0;
Ext.batchLayouts(function(){
me.columns.each(function (col) {
if (col.config.flex) flex += col.config.flex
else if (col.config.width) width -= col.config.width
else width -= col.getWidth()
})
if (flex) {
me.columns.each(function (col) {
if (col.config.flex) {
newWidth = Math.round(width * col.config.flex / flex)
if (col.getWidth() != newWidth) col.setWidth(newWidth)
}
})
}
})
}
})
Problem: A column whose width is set this way is no longer user resizeable.
There is an easier workaround (according to https://fiddle.sencha.com/#view/editor&fiddle/2kgh):
Just duplicate the flex property of the column in its child items.
Ext.create('Ext.grid.Panel', {
title: 'Simpsons',
store: Ext.data.StoreManager.lookup('simpsonsStore'),
columns: [
{ text: 'Name', dataIndex: 'name', flex: 1,
items: [
{
xtype: 'textfield',
flex: 1
}
]
},

Accessing toolbar from extjs Grid

I have a requirement where I have a number instances of a custom Grid (called PackageGrid).
This Grid has a default Toolbar with a couple of buttons. However for each instance of the Grid that I create, some additional widgets can be added to the toolbar using the insert method on the toolbar like so :
tBar.insert(0, {xtype:'button'})
My first approach was to define a custom toolbar and assign it to a variable, and then add that variable to my Grid, like so :
var tb = Ext.create('js.grid.Toolbar') //my custom toolbar
Ext.define('js.grid.PackageGrid', {
referenceToToolbar: tb,
extend: 'Ext.grid.Panel',
tbar: tb //this.toolbar
});
I hold a reference to the toolbar called referenceToToolbar. I then later grab this toolbar reference and add my widgets.
this.packageGrid = Ext.create('js.grid.PackageGrid')
var tBar = this.packageGrid.referenceToToolbar;
tBar.insert(0, {....})
The problem with this approach is that when I add widgets using tBar.insert(..) to my grid instances, ALL of my grids isntances get the same widgets... because, while the Grids are seperate instances, there is only one toolbar instance shared across all grids (tb).
I have tried playing around with the initComponent method to create an instance of the toolbar.
Basically I need ONE instance of a toolbar for ONE instance of my grid. And then be able to get a reference to that toolbar (before render time), and add some more widgets.
Can that be done?
You can pass additional toolbar item as configuration into grid. Then in grid's initComponent method you can create grid's tbar with merged items (shared and additional).
So your grid definition could be like this:
Ext.define('js.grid.PackageGrid', {
extend: 'Ext.grid.Panel',
initComponent: function() {
var me = this;
me.initTbar();
me.callParent();
},
initTbar: function() {
var me = this;
var tbarItems = [{
xtype: 'button',
text: 'Shared Button'
}];
if (me.aditionalTbarItems && me.aditionalTbarItems.length) {
tbarItems = me.aditionalTbarItems.concat(tbarItems);
}
me.tbar = tbarItems;
}
});
Then you can pass additional toolbar items in configuration when you are creating instance of your grid:
var grid1 = Ext.create('js.grid.PackageGrid', {
title: 'Grid 1',
aditionalTbarItems: [{
xtype: 'button',
text: 'Grid 1 Button'
}],
renderTo: Ext.getBody()
});
Fiddle with example: https://fiddle.sencha.com/#fiddle/70q

ExtJS 4 buttons in grid to edit, delete a row. open edit-form in a new tab

Basically my problem is splited into 2 parts. There are examples in the ExtJS 4 examples for extending a grid. but they are not working :( I'm using ExtJS 4 in the new recommended mvc application pattern.
Add a first column into a grid with buttons for editing and deleting
The grid is the first tab of a tabpanel. If the edit button is pressed a new tab should be created and bound to the store.
A new button should open a tab with a empty form bound to a store
Has anyone experiences with this? Any working code examples? I appreciate your help! Thx!
I have found a way to add buttons (or more correctly images).
So you need add new column with xtype: 'actioncolumn', and describe each button (image) as item.
E.g.:
...
columns: [
{
text: 'Name',
dataIndex: 'registrant_name',
flex: 1
}, {
xtype: 'actioncolumn',
width: 40,
items: [{
icon: 'path_to_img',
handler: function(grid, rowIndex, colindex) {
alert('click!');
}
}]
}
],
...
Also link on doc page:
http://docs.sencha.com/ext-js/4-0/#!/api/Ext.grid.column.Action

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