I'm facing a dilemma working with an Ext-JS GridPanel: the data used to load its store is dynamic so I don't know beforehand how many rows will need to be shown on the grid.
As such, I'm having a hard time with the grid's height: I've tried setting autoHeight to true but the grid will only display the first row, hiding the rest; when I set its height explicitly, white space appears on the grid if the number of rows doesn't fill the space specified by the height.
Ideally, the grid should expand/shrink vertically to show all of its rows.
Is there any way to make the grid's height dynamic, based on the number of rows it'll contain?
I could wait for the grid to render, get a count of rows and recalculate the grid's height based on that but it seems hacky and I'm looking for something cleaner.
This is my code for reference:
var store = new Ext.data.ArrayStore({fields:[{name: 'sign_up_date'}, {name: 'business_name'}, {name: 'owner_name'}, {name: 'status'}]});
// buildResultsArray is a method that returns arrays of varying lengths based on some business logic. The arrays can contain no elements or up to 15
store.loadData(buildResultsArray());
var resultsGrid = new Ext.grid.GridPanel({
store: store,
columns: [
{id: "sign_up_date", header: "Sign Up Date", dataIndex: "sign_up_date", width: 70},
{id: "business_name", header: "Business Name", dataIndex: "business_name", width: 100},
{id: "owner_name",header: "Owner Name", dataIndex: "owner_name", width: 100},
{id: "status", header: "Sign Up Status", dataIndex: "status", width: 70}
],
stripeRows: true,
columnLines: true,
enableColumnHide: false,
enableColumnMove: false,
enableHdMenu: false,
id: "results_grid",
renderTo: "results_grid_div",
//height: 300,
autoHeight: true,
selModel: new Ext.grid.RowSelectionModel({singleSelect: false})
});
Thanks for the help.
In ExtJS 3 it's not working out-of-box, but it's easy to implement by extending GridView:
AutoGridView = Ext.extend(
Ext.grid.GridView,
{
fixOverflow: function() {
if (this.grid.autoHeight === true || this.autoHeight === true){
Ext.get(this.innerHd).setStyle("float", "none");
this.scroller.setStyle("overflow-x", this.scroller.getWidth() < this.mainBody.getWidth() ? "scroll" : "auto");
}
},
layout: function () {
AutoGridView.superclass.layout.call(this);
this.fixOverflow();
},
render: function(){
AutoGridView.superclass.render.apply(this, arguments);
this.scroller.on('resize', this.fixOverflow, this);
if (this.grid.autoHeight === true || this.autoHeight === true){
this.grid.getStore().on('datachanged', function(){
if (this.ownerCt) { this.ownerCt.doLayout(); }
}, this.grid, { delay: 10 });
}
}
}
);
Usage:
new Ext.grid.GridPanel({
autoHeight: true,
view: new AutoGridView()
});
Related
I have a tabulator table with many items, and moving a row outside the displayed range of rows involves a number of steps (moving, dropping, scrolling, then moving again, etc.)
Has anyone come up with a method to scroll the table when the user drags a row above or below the displayed range? Here is a gif and a JSFiddle which demonstrates the problem.
https://jsfiddle.net/sunny001/puqwemnf/5/
const data = [];
for (let i = 0; i < 10000; i++){
data.push({id: i, name: 'name' + i})
}
const table = new Tabulator('#table', {
height: 400,
data: data,
movableRows: true,
columns: [
{
rowHandle: true,
formatter: "handle",
headerSort: false,
frozen: true,
width: 30,
minWidth: 30
},
{field: 'id', title: 'id'},
{field: 'name', title: 'name'}
],
selectable: true
})
I have a Panel and in that panel I am loading grid dynamically.
Here is code for panel
{
xtype: 'panel',
region: 'center',
frame: true,
scrollable: true,
itemId: 'MyGrid',
reference: 'MyGrid',
layout: {
type: 'vbox',
align: 'stretch'
},
items: []
}
and Sample of grid.
Ext.define("MyApp.view.MYGrid", {
extend: 'Ext.grid.Panel',
alias: 'widget.MyGrid',
requires: [
'Ext.grid.filters.Filters',
'Ext.form.field.ComboBox',
],
emptyText: 'No data available.',
disableSelection: true,
margin: '3 3 0 3',
collapsible: true,
multiSelect: false,
closable: true,
columnLines: true,
uniqueFields: [],
});
initComponent: function() {
var me = this;
me.fields = me.prepareFields(me.headersXmlDoc);
me.columns = me.prepareColumns(me.headersXmlDoc);
me.store = me.prepareGridStore(me.headersXmlDoc);
this.callParent(arguments);
},
Now when Grid have enough data then both horizental and vertical scroll is coming correctly but When grid have less data with more columns scrollbar is coming down. I supposed just beow the last record but it comming in down.
All the grid is taking same height though it have a less record.
Example pic
https://i.stack.imgur.com/RKdTb.png
I want scrollbar just below the last data. By debugging I found layout : fit
But not sure how to overcome out from that.
Can anybody help me that. Thanks for help.
You need to apply overflowY as true for grid.I don't think there is some problem with fit layout.If above config doesn't work share some fiddle.
I have the following EditorGridPanel on extJS:
http://jsfiddle.net/VDFsq/1/
Ext.onReady(function () {
var myData = [[ '<SPAN STYLE=\"text-align:Left;font-family:Segoe UI;font-style:normal;font-weight:normal;font-size:12;color:#000000;\"><P STYLE=\"font-family:Arial;font-size:16;margin:0 0 0 0;\"><SPAN><SPAN>HTML </SPAN></SPAN><SPAN STYLE=\"font-weight:bold;color:#FF0000;\"><SPAN>FORMAT</SPAN></SPAN><SPAN><SPAN> TEST<BR />TEST</SPAN></SPAN></P></SPAN>', "lisa#simpsons.com", "555-111-1224"],
[ 'Bart', "bart#simpsons.com", "555-222-1234"],
[ 'Homer', "home#simpsons.com", "555-222-1244"],
[ 'Marge', "marge#simpsons.com", "555-222-1254"]];
var store = new Ext.data.SimpleStore({
fields:[ {
name: 'name'
},
{
name: 'email'
},
{
name: 'phone'
}],
data: myData
});
var grid = new Ext.grid.EditorGridPanel({
renderTo: 'grid-container',
columns:[ {
header: 'Name',
dataIndex: 'name',
width:200
}
],
store: store,
frame: true,
height: 240,
width: 500,
enableColumnMove :false,
stripeRows: true,
enableHdMenu: false,
border: true,
autoScroll:true,
clicksToEdit: true,
title: 'HTML in Grid Cell',
iconCls: 'icon-grid',
sm: new Ext.grid.RowSelectionModel({
singleSelect: true
})
});
grid.on({
celldblclick: function() {alert(1);}
});
});
the problem is, when the gridCell contains HTML data (which is my situation) when you double click on the cell with html the grid does not fire the event celldblclick.
in my application I need to display that kind of html in the grid.
how can fix this problem? anyway to bubble the event from the html to the grid?
Thanks
It seems that there is some limits to dom tree deep inside your structure. I think it is not good idea to put html into grid - if you can unify it structure - may be templates would be more useful.
Try this instead of your HTML:
"<div ondblclick=\"alert('1!')\">1<div ondblclick=\"alert('2!')\">2<div ondblclick=\"alert('3!')\">3<div ondblclick=\"alert('4!')\">4</div>3</div>2</div>1</div>"
Event inheritance works fine in this HTML, but works only 2 levels deep in your EXt example.
NOTE: if you try
grid.on('rowdblclick', function(eventGrid, rowIndex, e) {
console.log('double click');
}, this);
you will not get problem (but, obviously, you can dblclick only rows in this way)
At present I'm getting all the cells (with editable:true) in the row editable in which i clicked and not only the clicked the cell. The table is similar to the table in this link: http://www.ok-soft-gmbh.com/jqGrid/ClientsideEditing4.htm. I've gone through the link: http://www.trirand.com/jqgridwiki/doku.php?id=wiki:cell_editing, but didn't help (may be due to my fault in the way i tried) and also tried the answers given in stackoverflow related questions (used the attributes: cellEdit: true, cellsubmit: "clientArray").
Please help me using the above link as reference http://www.ok-soft-gmbh.com/jqGrid/ClientsideEditing4.htm (I think mainly the "onSelectRow", "ondblClickRow" functions need to be updated. i tried onSelectCell etc. but failed! ).
Thanks in advance.
If you need to use cell editing you have to include cellEdit: true in jqGrid definition. If you use local datatype then you should use cellsubmit: "clientArray" additionally. If you want to save data on the remote source you have to implement editing in your server code and specify cellurl option of jqGrid. The documentation describes what jqGrid send to the server on saving of cell.
I'm currently working on an Angular 2 app with Typescript, and I had a different need where I wanted to be able to click a row in the grid, but only have one cell editable. I didn't like the user experience where the user had to click the actual cell to edit it. Instead, clicking the row highlights the row and then makes the one cell editable. Here's a screenshot:
The trick was that I needed to set cellEdit to false on the grid and then set the individual column editable to true when declaring my column model array, and write a change event for the editoptions of the column. I also had to write code for the the onSelectRow event of the grid, to keep track of the current row selected and to restore the previous row selected. A snippet of the Typescript code is below:
private generateGrid() {
let colNames = ['id', 'Name', 'Total', 'Assigned', 'Distributed', 'Remaining', 'Total', 'Assigned', 'Remaining', 'Expiration'];
let self = this;
// declare variable to hold Id of last row selected in the grid
let lastRowId;
let colModel = [
{ name: 'id', key: true, hidden: true },
{ name: 'name' },
{ name: 'purchasedTotalCount', width: 35, align: 'center' },
{ name: 'purchasedAssignedCount', width: 35, align: 'center' },
{ name: 'purchasedDistributedCount', width: 35, align: 'center' },
{ name: 'purchasedRemainingCount', width: 35, align: 'center' },
// receivedTotalCount is the only editable cell;
// the custom change event works in conjunction with the onSelectRow event
// to get row editing to work, but only for this one cell as being editable;
// also note that cellEdit is set to false on the entire grid, otherwise it would
// require that the individual cell is selected in order to edit it, and not just
// anywhere on the row, which is the better user experience
{ name: 'receivedTotalCount',
width: 35,
align: 'center',
editable: true,
edittype: 'text',
editoptions: {
dataEvents: [
{
type: 'change', fn: function(e) {
//TODO: don't allow decimal numbers, or just round down
let count = parseInt(this.value);
if (isNaN(count) || count < 0 || count > 1000) {
alert('Value must be a whole number between 0 and 1000.');
} else {
self.updateLicenses(parseInt(lastRowId), count);
}
}
},
]
}
},
{ name: 'receivedAssignedCount', width: 35, align: 'center' },
{ name: 'receivedRemainingCount', width: 35, align: 'center' },
{ name: 'expirationDate', width: 45, align: 'center', formatter: 'date' }
];
jQuery('#licenseManagerGrid').jqGrid({
data: this.childTenants,
datatype: 'local',
colNames: colNames,
colModel: colModel,
altRows: true,
rowNum: 25,
rowList: [25, 50, 100],
width: 1200,
height: '100%',
viewrecords: true,
emptyrecords: '',
ignoreCase: true,
cellEdit: false, // must be false in order for row select with cell edit to work properly
cellsubmit: 'clientArray',
cellurl: 'clientArray',
editurl: 'clientArray',
pager: '#licenseManagerGridPager',
jsonReader: {
id: 'id',
repeatitems: false
},
// make the selected row editable and restore the previously-selected row back to what it was
onSelectRow: function(rowid, status) {
if (lastRowId === undefined) {
lastRowId = rowid;
}
else {
jQuery('#licenseManagerGrid').restoreRow(lastRowId);
lastRowId = rowid;
}
jQuery('#licenseManagerGrid').editRow(rowid, false);
},
});
}
Additionally, I wanted the escape key to allow the user to abort changes to the cell and then restore the cell to its previous state. This was accomplished with the following Angular 2 code in Typescript:
#Component({
selector: 'license-manager',
template: template,
styles: [style],
host: {
'(document:keydown)': 'handleKeyboardEvents($event)'
}
})
// handle keypress so a row can be restored if user presses Escape
private handleKeyboardEvents(event: KeyboardEvent) {
if (event.keyCode === 27) {
let selRow = jQuery('#licenseManagerGrid').jqGrid('getGridParam', 'selrow');
if (selRow) {
jQuery('#licenseManagerGrid').restoreRow(selRow);
}
}
}
I using Ext JS 2.3.0 and have a GridPanel that looks like this:
I want to expand the width of the column such that the scroll bar is pushed over the extreme right of the panel, thus eliminating the empty space to the right of the scroll bar.
The relevant code is shown below:
var colModel = new Ext.grid.ColumnModel([
{
id: 'name',
header: locale['dialogSearch.column.name'],
sortable: true,
dataIndex: 'name'
}
]);
var selModel = new Ext.grid.RowSelectionModel({singleSelect: false});
this._searchResultsPanel = new Ext.grid.GridPanel({
title: locale['dialogSearch.results.name'],
height: 400,
layout: 'fit',
stripeRows: true,
autoExpandColumn: 'name',
store: this._searchResultsStore,
view: new Ext.grid.GridView(),
colModel: colModel,
selModel: selModel,
hidden: true,
buttonAlign: 'center',
buttons: [
{
text: locale["dialogSearch.button.add"],
width: 50,
handler: function () {
}
},
{
text: locale["dialogSearch.button.cancel"],
width: 50,
handler: function () {
entitySearchWindow.close();
}
}
]
});
You should use the forceFit config for the grid view:
this._searchResultsPanel = new Ext.grid.GridPanel({
title: locale['dialogSearch.results.name'],
height: 400,
layout: 'fit',
viewConfig: {
forceFit: true
}, ....
I'm not sure if this isn't redundant so you can remove this part view: new Ext.grid.GridView(),
The problem is not the column but the grid itself which does not stretch to fill the window body completely.
Put the layout: 'fit' property onto the window config instead of onto the grid config (where it needs to be removed). You should also remove the height property because the grid height will determined by the window's size.
Add
flex: 1,
to one of the the columns config