How to make AG-Grid to have fluid layout - ag-grid

I'm trying to use the AG-Grid for my project and I've been trying to play around with it for a while now, but one problem I came across with this grid is that I can't easily make the columns to auto resize whenever the div or browser resizes like a fluid layout.
I know there is the .api.sizeColumnsToFit() function to use which will do it once it's called, but this would mean I will to manually add a listener or some sort to the window to check if it has been resize and call it if it has?? Is there a better way to achieve this??
Thanks

Try calling sizeColumnsToFit whenever the grid onGridSizeChanged event fires. The following will run when the grid first loads/ or data adjusts (onModelUpdated) and when the grids size changes.
i.e
this.gridOptions = <GridOptions>{
onModelUpdated: () => {
this.gridOptions.api.sizeColumnsToFit();
},
onGridSizeChanged: () => {
this.gridOptions.api.sizeColumnsToFit();
}
};

Related

How to prevent closing of cell editing in ag-grid on "Other Cell Focus"

I am working on an editable table in Angular application with ag-grid library. I would like to keep editing cells (in full row edit mode) until I finish with it and then close the editors manually via API. The problem is that the editor is closing on other cell click/focus (on some other line) as described here:
The grid will stop editing when any of the following happen:
Other Cell Focus: If focus in the grid goes to another cell, the editing will stop.
I cannot figure out how to disable this, if it is possible. Installing the onCellMouseDown() hook does not help, because the cellFocused event is fired before cellMouseDown. Therefore, the editing stops before I have a chance to intercept the mousedown event.
Here is my stackblitz little extract with related pieces of code.
The need for such scenario is that I want to validate the entry and not to allow a used to quit the editing if the form is not valid. The only workaround I found so far is that on any click outside of editing cells when the editor closing I reopen it right away in onRowEditingStopped() hook unless the editor has been closed via 'OK' button.
After all, I have managed to provide a custom solution that fits exactly into this problem which I was facing also.
First thing is to disable pointer events to non edited rows when a specific row is currently being edited. On Ag-grid's 'cellEditingStarted' callback I have added the following code:
public cellEditingStarted(event: any): void {
//not all rows are on dom ag-grid takes care of it
const nonSelectedGridRows = document.querySelectorAll('.ag-grid-custom-row:not(.ag-row-selected):not(.ag-row-editing):not(.pointer-events-none)');
forEach(nonSelectedGridRows, row => {
row.classList.add("pointer-events-none");
});
}
Because not all rows exist on dom (Ag-grid creates and destroys while you are scrolling )when a specific cell is being edited, I have also added a rowClassRule which is applied when rows are being created:
this.rowClassRules = {
'pointer-events-none': params => {
if (params.api.getEditingCells().length > 0) {
return true;
}
return false;
}
};
scss:
.pointer-events-none {
pointer-events: none
}
By disabling pointer events, when you click on a non edited cell the cell won't get focus and thus the currently edited cell will stil remain on edit mode. You can provide your own custom validation solution and close the editor manually through API. When you are done, you have to enable pointer events to all grid rows back again:
private enablePointerEvents(): void {
//not all rows are on dom ag-grid takes care of it
const nonSelectedGridRows = document.querySelectorAll('.ag-grid-custom-row.pointer-events-none');
forEach(nonSelectedGridRows, row => {
row.classList.remove("pointer-events-none");
});
}
I implemented the same above approach in Ag-Grid React.
I used getRowStyle callback for adding the css pointerEvents: none on dynemic basis.
It seems to be working for me fine.
Please refer the below code
const getRowStyle = (params) => {
// this is not initialized in read mode
// condition for me ==> currentEditRowIndex.current !== null && params.node.rowIndex !== currentEditRowIndex.current
if (someCondition for Row other than inline edit row) {
return { pointerEvents: "none" };
}
return null;
};
After adding this whenver you start the editing..You will need to call redrawRows so that css changes can be applied.
Hope this will help. Thank You!!
Thought I would share another solution that has been working out okay for me so far.
Using 'pointer-events-none' as suggested in the other answer is flawed because the Enter key can also close the editor.
In my case, I want to prevent the editor from closing when client side validation has failed and the data is invalid. When my conditions are met, I call stopPropagation() on the events to prevent the editor close from happening in the first place. It still has potential problems:
It cancels mousedown, dblclick, keydown, focusout and click for all elements that have a class name starting with ag- so if you happen to use this class prefix for other controls on the page, it could interfere. It also means any controls within the grid (sorting, resizing, etc.) don't work while the condition is met.
Calling stopPropagation() could potentially interfere with your own custom controls. So far I've been okay if I dont use the ag- prefix within the markup from my own custom cell editors and renderers
I hope they can add a proper API function to cancel the row/cell stopEditing function in the future.
["mousedown", "dblclick", "keydown", "focusout", "click"].forEach(function (eventName) {
document.addEventListener(eventName, function (e) {
if ( conditionForCancelingIsMet() ) {
// this appears to cancel some events in agGrid, it works for
// preventing editor closing on clicking other cells for example.
// It would be ideal if this worked for all ag-grid specific events
// and had a proper public API to use!
e["__ag_Grid_Stop_Propagation"] = true;
}
// convert element classList to normal js array so we can use some()
var classArray = [].slice.apply(e.target.classList);
if ( conditionForCancelingIsMet() && classArray.some(c => c.startsWith("ag-")) ) {
// unfortunately some events like pressing the 'enter' key still
// require stopPropagation() and could potentially interfere with unrelated controls
e.stopPropagation();
}
}, true);
});

How do you stop scrolling to top when grid store is reloaded

I have an app that uses ExtJS 3.3.0. It uses an EditorGridPanel in which after the store is reloaded - I would like it to preserve the scroll position of the grid rather than sending it back up to the top.
Because this is an earlier version of ExtJS - this DOES NOT work:
viewConfig: {
preserveScrollOnRefresh: true
}
So far the only thing I can come up with is to save the position of the scroll bar prior to loading - and then reset the position once the reload is complete.
I can get as far as saving the position:
var scrollPos;
bodyscroll: function(sl, st) {
scrollPos = st;
},
However I can't figure out how to set the position afterwards.
Any suggestions?
Thanks in advance.
There might be multiple ways to do this but one way is to use the scroller element, which is accessible through the grid's gridview. See fiddle here: Grid scoll save/restore.
To get scroll value (which you've already got figured out):
var top = grid.getView().scroller.getScroll().top;
To restore:
grid.getView().scroller.scrollTo('top',top);

Ag-Grid expand row

Im using Ag-grid to control my table, but i want in my group that stores a list of rows instead of having to make the row group expand in 2 clicks, i want to be on 1 click.
If i click on the icon arrow it works, but if i click on the title row it only opens on 2 clicks.
I already tried to find in the documentation any information about it, but cant find nothing.
Here is a example from the documentation.
https://ag-grid.com/javascript-grid-tree/index.php
example image:
We are now recommended not to use the onGroupExpandedOrCollapsed, so this should now be...
This will also update the icons and animate the rows, which onGroupExpandedOrCollapsed won't.
onRowClicked(params) {
params.node.setExpanded(!params.node.expanded);
}
This will toggle the expansion, use params.node.setExpanded(true) if you want the rows to just stay open.
You can listen to events on either a row or cell clicked, and expand nodes accordingly.
For example to expand a row based on a click you could do the following:
onRowClicked: (params) => {
// update the node to be expanded
params.node.expanded = true;
// tell the grid to redraw based on state of nodes expanded state
gridOptions.api.onGroupExpandedOrCollapsed(params.rowIndex)
}
This should be in the documentation - I'll update it to reflect this information.
In the column definition, you can use the onCellClicked(params) function to tell it to do something when the cell is clicked. I tried looking for an expand function, but I could only find expandAll() which I don't think you will want. So what I would do is just use jquery or simple DOM selection to click on the expand icon inside of that cell.
this one works
onRowClicked(params) {
params.context.setExpand.onExpandClicked(params.rowIndex, params.node.rowHeight);
}

React-dnd - change styling of dropTargets on dragStart

I got a app that shows multiple pages, which are dragable. As the content of those can get very long I want to show only the page-name and limit the height of the page to about 50px on beginDrag() and reset the height to auto on endDrag(). Unfortunately this doesnt work, the styles get just ignored. I think this happends because react-dnd needs to keep the proportion of the elements so it can handle the drop-targets and knows which component is at which position. Is there any other way to accomplish this?
If you use a dragPreview then it will use that instead of the screenshot-ed component, similar to what he does in the tutorial (http://gaearon.github.io/react-dnd/docs-tutorial.html):
componentDidMount: function () {
var connectDragPreview = this.props.connectDragPreview;
var myPlaceholder = <Placeholder /> // A fake component with the height you want
myPlaceholder.onload = function() {
connectDragPreview(myPlaceholder);
}
}
(Note that you'll have to inject the connectDragPreview through the collector like he did as well)
I'm not quite sure I understand the problem but may be connectDragPreview can help you?
Some useful info here

How to save scroll position on an extjs form?

I have a long form with comboboxes and buttons that add element to the form. Every time combobox's value gets upldated or elements get added, it scrolls up to the top of the form. I want the scrollbar to retain its position. I tried saving current scroll position by doing
this.myForm.getScrollPosition();
But I get getScrollPosition is not a function error.
Any help on this?
If you are using extjs there is a way to manipulate the scroll using the Ext.dom.Element class, each component in Extjs inherits from it, then if you add a new component that modifies the height or width of your form, you can first get the height and width of that component using:
var newcompwidth = comboboxexample.getWidth();
var newcompheight = comboboxeample.getHeight();
Later you can modify the scroll value using scrollTo method like this:
myformcontainer.getEl().scrollTo('Top',myformcontainer.getEl().getScroll().top - newcompheight);
myformcontainer.getEl().scrollTo('Top',myformcontainer.getEl().getScroll().left - newcompwidth);
there are other methods like scrollBy or scroll but I didn't test it yet, I guess this will help you.
the docs: http://docs.sencha.com/extjs/4.1.0/#!/api/Ext.dom.Element