ag-Grid: extend rows till right edge if columns don't occupy full width - ag-grid

In ag-Grid, if the columns occupy a smaller space than the width of the grid, a blank hole appears on the right of the last column. Please see below (example taken from ag-Grid docs):
The UX designers on my team don't like that. They would like to see the rows extended all the way to the right to balance out the look. Is this possible to do with ag-Grid?
Edit: We don't want to use the sizeColumnsToFit option, because on large monitors it produces very wide columns and the grid becomes unreadable. We want to use the autoSize option to compact the columns and fill the hole on the RHS with blank stripes as suggested above.

Yes it is possible. You can call the sizeColumnsToFit function on the ag-Grid api which will fill out the width of the table with the columns.
Take a look at documentation.
Here is a plunker example.
EDIT
Use the property suppressSizeToFit and set it to true to when you call sizeColumnsToFit, it won't have an affect. Apply this property to the defaultColDef and set it to false for the last column. This was, when you call sizeColumnsToFit, only the last column will be set to full width. See the updated plunker above.

this is how i do it:
/**
* if there is "dead space" present on the grid, the columns will be auto sized to fill the gap
* #param gridApi
* #param columnApi
*/
resizeColumnsToFit(gridApi: GridApi, columnApi: ColumnApi, allowShrink = false) {
if (allowShrink) {
gridApi.sizeColumnsToFit();
} else {
const gridBodyWidth = document.getElementsByClassName("ag-root-wrapper")[0].clientWidth; // todo: use grid's id instead of [0] to allow multiple grids on a page
const allColumnsWidth = columnApi.getAllDisplayedColumns().map(c => c.getActualWidth()).reduce((a, b) => a + b, 0);
if (gridBodyWidth > allColumnsWidth) {
gridApi.sizeColumnsToFit();
}
}
}
This method will size columns to fit only when there is "dead" space on the right. Optionaly set allowShrink to true to force resizing even if there is no dead space

I had the same situation and resolved with the following css override:
.ag-center-cols-container {
width: 100% !important;
}

One possible option I've been playing with is adding a fake column at the end to fill the remaining space. To do so, you just need to add a column with options similar to the following to the end of your list of columns:
{
flex: 1,
headerName: '',
}
See this plunker forked from #ViqMontana's example above.
It's not a perfect solution, but wanted to mention it here in case it helps.

This works like Craig Weston's answer but without the need for !important:
.ag-center-cols-container {
min-width: 100%;
}

Related

Unmerge and Assign Values Only Vertically or Horizontally Openpyxl

Using the answer provided by aka863 here: How to split merged Excel cells with Python?
I can unmerge, fill values and copy the styling. My questions is how to make the value assigning/filling process configurable.
I want the user to be able to choose whether the values will be filled vertically/horizontally.
I have tried changing the last loop where we assign the top_left_cell_values to unmerged cells. However I couldn't find a way to make it horizontal/vertical configurable. (I'm planning to use radio buttons and tkinter for this)
Its certainly possible to have the code de-merge cells and fill cells in whichever direction, vertically or horizontally regardless of which way the merge was originally. Or not fill at all, so only the top left cell retains the 'value' of the previously merged cells, which is default on unmerge.
Changing the direction of the fill requires some change and re-calculation on the max row and column values in the iter_rows loop, but is simple enough.
However it seems in your last comment you just want to give the user the option to fill or not fill on horizontal merges. In that case you just need to ask the question, and then run the iter_rows loop only if the response is yes.
The code sample below is based on the answer referenced question.
I'm assuming only single line horizontal merges since you dont mention what if anything should be done with vertical merges in the comment.
The code does initially check and indicate the merge direction either vertically or horizontally so it can be included take some action if a merge is vertical.
On code run after displaying the range and direction of the merge, the question is asked to fill, yes or no. If yes the cells are de-merged and all cells filled with the top left cell value using the iter_rows loop. If answer no then the cells are just de-merged.
from openpyxl import load_workbook
from openpyxl.utils.cell import range_boundaries
wb = load_workbook(filename='foo.xlsx')
st = wb['Sheet1']
mcr_coord_list = [mcr.coord for mcr in st.merged_cells.ranges]
direction_dict = {'v': 'vertical', 'h': 'horizontal'}
for mcr in mcr_coord_list:
print('---------------------------------------------------\n')
merge_direction = ''
min_col, min_row, max_col, max_row = range_boundaries(mcr)
top_left_cell_value = st.cell(row=min_row, column=min_col).value
if min_col == max_col:
merge_direction = 'v'
elif min_row == max_row:
merge_direction = 'h'
print(f"The cell range {mcr} is merged {direction_dict[merge_direction]}ly with the data '{top_left_cell_value}'")
while True:
demerge_fill = input('Do you want the de-merge to fill all cells(y|n)? ')
if demerge_fill.lower() in ["y", "n"]:
break
else:
print('Invalid response')
st.unmerge_cells(mcr)
if demerge_fill == 'y':
for row in st.iter_rows(min_col=min_col, min_row=min_row, max_col=max_col, max_row=max_row):
for cell in row:
cell.value = top_left_cell_value
else:
print(f"Only the top left cell {mcr.split(':')[0]} will contain the data!")
wb.save('merged_tmp.xlsx')

increase height of a specific row

Initially, all rows will have the same height of 50. When a cell is focused,if it has more content and requires more height, I need to increase the height of that particular cell. If that is not possible, atleast that entire particular row's height has to be increased. The remaining rows should not get effected.
I would make use of rowSelection api particularly the selected property of each rowNode.
You can define getRowHeight in html [getRowHeight]="getRowHeight"
and (selectionChanged)="onSelectionChanged($event)"
And define getRowHeight like this -
this.getRowHeight = function(params) {
return params.node.selected ? 100 : 50; // if selected height is 100 else default 50
}
and then in your onSelectionChanged,
onSelectionChanged() {
this.gridApi.resetRowHeights();
}
The reason you would want to piggyback on selected attribute is because it is maintained by ag-grid for each row.
You could do something similar by implementing the callback onCellFocused but then you will have to maintain a similar attribute for each row because you also need to adjust the height once the focused row is out of focus which might be an expensive operation.

Ag-grid column grouping resize issue

In my developed grid with column grouping, there is white empty space is appear at end when resize the columns. Any Suggestion?[![enter image description here][1]][1]
You can call sizeColumnsToFit() after columnRowGroupChanged event:
columnRowGroupChanged A row group column was added or removed.
.html template event binding
(columnRowGroupChanged)="groupChanged($event)"
or .ts gridOptions event binding (don't forget to define [gridOptions] in .html)
this.gridOptions:{
onColumnRowGroupChanged : this.groupChanged.bind(this)
}
handling
groupChanged(params){
params.api.sizeColumnsToFit();
}
DEMO
Starting from ag-grid 23.1.0, we no longer have to use sizeColumnsToFit. Instead, in column definition, add flex: 1 to the last visible column.
This prevents all annoying jumps and weird grid behavior when resizing columns. In case user enlarge the column, horizontal scrollbar will appear, which is the expected behavior.
Please go over your code and change sizeColumnsToFit to the flex solution.
Flex also gives you control over relative column sizes, you can read more about it in the docs: https://www.ag-grid.com/javascript-grid-resizing/.
Example:
columnDefs = [{...}
...
{
headerName: 'HeaderA',
field: 'name',
...
flex: 1, // Adding this to last column definition
}]

Auto Size all columns to fit content

All my searches turned up for sizeColumnsToFit and autoSizeColumns which is not what I want.
My grids have many columns, so it scroll horizontal which is fine
But I cannot know in advance what would be the most space needed for the widest text in a column, so want the grid to auto size all columns to accommodate for whatever is the longest line of text in the cell.
Can one do that? (pretty much like have nowrap on a html table column, not that ag-grid wrap text, it just hide what is too long)
Grid Resizing:
https://www.ag-grid.com/javascript-grid-resizing/
sizeColumnsToFit - this tries to squeeze all the columns in the view - no horizontal scrolling
autoSizeAllColumns - this tries to size all columns to to fit the data - horizontal scrolling
// If you need to resize specific columns
var allColIds = params.columnApi.getAllColumns()
.map(column => column.colId);
params.columnApi.autoSizeColumns(allColIds);
// If you want to resize all columns
params.columnApi.autoSizeAllColumns();
I passed through this and it took me some time to make it work the way I wanted to, by that I mean :
Use all the available space
Make each column take the width required to display its content correctly
Solution :
Add the width parameter for each column (requires some manual tuning to set the right values)
Call gridApi.sizeColumnsToFit() in the onGridReady which will resize to take the available space while making sure that columns having bigger width will take more space
const gridOptions = {
...
columnDefs: [
{
...,
width: 100
},
{
...,
width: 50
},
...
],
...
onGridReady: (event) => event.api.sizeColumnsToFit();
};
Simply use flex instead of width in the column definitions. The grid will adjust automatically.
You can find a complete example for auto resizing all column.
column-sizing
Simply call autoSizeColumns() function, all columns will be resized according to content.
gridColumnApi.autoSizeColumns(allColumnIds, skipHeader);

How to create a GtkPixbuf from a stock item llike (new_from_stock)?

I want to get a stock item to use it in a treeview but I can't get it as a pixbuf directly as there is no new_from_stock method for pixbufs!!
say you want to get a pixbuf from stock_item.
There are 2 ways:
First (easy):
pixbuf = gtk_widget_render_icon ( widget, stock_item, size )
Second (hard):
You need to look for it in the list of default icon factories:
icon_set = gtk_style_lookup_icon_set ( style, stock_item )
OR:
icon_set = gtk_icon_factory_lookup_default ( $stock_item )
then check available sizes with get_sizes.
Check if the size you want is available or get the largest size which will be the last in the returned list.
Then you need to render it to get the pixbuf:
pixbuf = gtk_icon_set_render_icon ( icon_set, style, direction, state, size, widget )
Then scale it to whatever size you want using:
gdk_pixbuf_scale_simple ( pixbuf, width, height, GdkInterpType )
Hope you got it
Are you aware of the icon-name property in GtkCellRendererPixbuf? That should solve the problem of showing a stock icon in a treeview.
A slightly easier (and more future-proof) version of ophidion's answer is to do the following:
#define ICON_NAME "go-next"
#define ICON_SIZE 96 /* pixels */
GError *error = NULL;
GtkIconTheme *icon_theme = gtk_icon_theme_get_default();
GdkPixbuf *pixbuf = gtk_icon_theme_load_icon(icon_theme, ICON_NAME, ICON_SIZE,
GTK_ICON_LOOKUP_USE_BUILTIN, &error);
Assuming you don't get an error, you can then put the resulting GdkPixbuf in a treemodel, or use it with a GtkButton, or whatever else you'd like to do with it.
As others have pointed out, GTK stock items are likely to be deprecated, so you should use names according to the Icon Naming Spec instead if you want to be future proof. See this Google Docs spreadsheet for the equivalent icon spec names for GTK stock items.
You can use gtk_image_new_from_stock(), then get the raw pixbuf using gtk_image_get_pixbuf().
But check out #jku's answer first, that sounds like the proper solution. I just wanted to add how you'd do it in any other context.