ag-Grid Master / Detail - Row Selection - ag-grid

Goals
I am trying to add row selection functionality which is connected between the master grid and detail grid.
When a checkbox on a master grid row is selected, I want to select all the checkboxes in the associated detail grid.
When a checkbox on a master grid row is deselected, I want to deselect all the checkboxes in the associated detail grid.
When only partial checkboxes inside of a detail grid are selected, I want the master grid row to show a partial selection icon in the checkbox.
I want to keep count of how many items were selected in all of the detail grids
Questions/Problems
All of this functionality already exists for Groups, but I cannot get it to work for Master/Detail. I've tried adding in the line that I believe should add this for Groups cellRendererParams: {checkbox: true}, but that does nothing for the detail grid.
I've also tried implementing the functionality myself, but I hit a couple of roadblocks.
I don't know how to set the partial-checkbox icon manually or if that's even possible.
I implemented the onSelectionChanged event handler for the detail grid, but inside of the function it looks like I can't access the Angular component context to update the count of selected items. Not sure how to pass in the context this.
Code that I have working so far:
When a checkbox on a master grid is selected/deselected, the checkboxes in the associated detail grid are all selected/deselected.
public onMasterRowSelected() {
this.gridOptions.api.forEachNode(masterRowNode => {
if(masterRowNode.isSelected()) {
this.gridOptions.api.getDetailGridInfo(`detail_${masterRowNode.id}`).api.selectAll();
} else {
this.gridOptions.api.getDetailGridInfo(`detail_${masterRowNode.id}`).api.forEachNode(detailRowNode => detailRowNode.setSelected(false));
}
});
}
Added the onSelectionChanged() event listener for the detail grid.
constructor() {
this.gridOptions = {
...
detailCellRendererParams: {
getDetailRowData: function(params) {
params.successCallback(params.data.items); // Defines where to find the detail fields out of the rowData object
},
detailGridOptions: {
rowSelection: 'multiple',
defaultColDef: {
sortable: true
},
getRowNodeId: function (rowData) {
return rowData.id; // detail items are indexed by id field
},
onSelectionChanged: function (params) {
console.log(this); // I expected this to print out my Angular component object, but instead it prints out this.gridOptions.detailCellRendererParams.detailGridOptions
console.log("TEST"); // I know that this function is successfully being called because this line is printed
this.selectedItems = 0;
params.api.forEachNode(detailRowNode => {
if(detailRowNode.isSelected()) {
this.selectedObs++; // I believe that this would work if I had access to the correct "this" context
}
});
},
columnDefs: [
{headerName: 'Column 1', field: 'column1', checkboxSelection: true},
{headerName: 'Column 2', field: 'column2'},
]
}
}
};
}

Here is an Angular example where you can push the parent component as a reference to the detail grid and set it as its context. Doing this allows you to register a component method as a callback for the detail grid's onRowSelected method.
https://stackblitz.com/edit/ag-grid-detailrow-selectcallback?file=src/app/app.component.ts

Move the onSelectionChanged(params) function to the same level as the detailCellRendererParams object.
internalOnSelectionChanged(params)
{
this.detailGridApi = params.api;
this.detailGridColumnApi = params.columnApi;
console.log(this);
}
Then, on the onSelectionChanged, do this:
onSelectionChanged: this.internalOnSelectionChanged.bind(this);
This solved my issues that were very similar to yours.

Related

Simple way to programatically remove all grouping and filtering

When the grid loads there is no grouping/filtering applied. I want to be able to remove any grouping/filtering which the user has applied manually i.e. get the grid format back to its original state.
You can do this with help of gridOptions of ag-grid. Try to do the below changes..
Initialize gridOptions if not yet along with column definitions and set the grid options in ag-grid.
Component.ts
this.gridOptions = {
defaultColDef: {
editable: true,
resizable: true,
filter: true
},
columnDefs: this.columnDefs,
rowData: this.rowData
};
clear the filters with like below
...
gridOptions.api.setFilterModel(null);
gridOptions.api.onFilterChanged();
...
component.html
<ag-grid .. [gridOptions] = "gridOptions" ..> </ag-grid>
You can see more about this in the ag-grid documentation.
you can define a function to reset everything
function ResetGrid(){
//clear filters
gridOptions.api.setFilterModel(null);
//notify grid to implement the changes
gridOptions.api.onFilterChanged();
//remove all pivots
gridOptions.columnApi.setPivotColumns([]);
// disable pivot mode
gridOptions.columnApi.setPivotMode(false);
//reset all grouping
gridOptions.api.setColumnDefs(columnDefs);
//where columDefs is the object you used while creating grid first time.
}
the above method does what you want but more sophisticated way to do this will be saving column state(it may be at iniital stage or later after certain operation).
function saveState() {
window.colState = gridOptions.columnApi.getColumnState();
window.groupState = gridOptions.columnApi.getColumnGroupState();
window.sortState = gridOptions.api.getSortModel();
window.filterState = gridOptions.api.getFilterModel();
console.log('column state saved');
}
function restoreState() {
if (!window.colState) {
console.log('no columns state to restore by, you must save state first');
return;
}
gridOptions.columnApi.setColumnState(window.colState);
gridOptions.columnApi.setColumnGroupState(window.groupState);
gridOptions.api.setSortModel(window.sortState);
gridOptions.api.setFilterModel(window.filterState);
console.log('column state restored');
}
function resetState() {
gridOptions.columnApi.resetColumnState();
gridOptions.columnApi.resetColumnGroupState();
gridOptions.api.setSortModel(null);
gridOptions.api.setFilterModel(null);
console.log('column state reset');
}
here is a demo
Here is how you can remove all filters and row groups. For more info, see GridApi.
gridApi.setFilterModel(null);
gridApi.setRowGroupColumns([]);
gridApi.onFilterChanged();
Live Example

AG-Grid render Bootstrap-Select as a dropdwon

I have implemented editable AG-Grid. In the grid, one of the column displays country of the player as shown below:
Now in last column, when user click on the cell, I want to display list of available countries as a dropdown.
Here by default AG-Grid displays normal dropdown. Which I want to replace with Bootstrap-select.
To achieve this, I have implemented custom selector and using Bootstrap-select library.
But when cell is clicked, Dropdown is not being rendered. I am not getting any error though in console.
Here is the code of my custom cell-editor:
var selectCellEdior = function () { };
selectCellEdior.prototype = {
init: function (params) {
selector = document.createElement('select');
for(var i = 0; i < params.values.length; i++) {
var option = params.values[i];
$('<option />', { value: option, text: option }).appendTo(selector);
}
this.cellSelector = selector;
$(this.cellSelector).selectpicker({ size: 'auto' });
},
getValue: function () {
return $(this.cellSelector).find('.btn-text').text();
},
getGui: function () {
return this.cellSelector;
},
destroy: function () {
$(this.cellSelector).remove();
}
};
Here is the Sample Code
I dont understand what is the issue.
The problem is the selectpicker jQuery method seems to add a display: none to the select element. Ag-Grid is adding it to the DOM you just can't see it. Additionally the getValue function is not returning the selected option's text.
The following changes to getValue and getGui will make the grid work:
...
getValue: function () {
return $(this.cellSelector).val();
},
getGui: function () {
this.cellSelector.style.display = 'block';
return this.cellSelector;
},
...
Here is the modified Plunker
For anyone looking at this now.... Ag-grid has a method afterGuiAttached that is called after the GUI has been attached to the Grid's cell. If you're noticing that the bootstrap-select still isn't "quite right" after following the instructions above, put ALL of the calls to selectpicker in afterGuiAttached instead of init or getGui. This will place the bootstrap-select into a div with the right classes it needs (dropdown, bootstrap-select, etc), and create all of the bootstrap-select elements that are properly shown/hidden.

group selection & checkbox in ag-Grid

In my Angular application I have a grid that is almost identical to the Group Selection example in the ag-Grid docs: https://www.ag-grid.com/javascript-grid-selection/#gsc.tab=0
My requirement is slightly different in that my expand button needs to both expand the row and select the row. As you see in the plunker example selection and expansion are two separate click events, but I am looking to select the row and expand that same row in one click, without having the user click on the checkbox and the expand button. I have tried doing this with css by making the checkbox transparent and placing it over the expand icon, but the click is highjacked so only one event will fire...
Is this possible in ag-Grid?
In my component by columnDefs for the column that has my checkbox and expand icon looks like so:
...
this.gridOptions.columnDefs = [
{
headerName: '', width: 100, cellRenderer: 'group',
// for parent row selection - checkboxes for parent rows
checkboxSelection: function(params) {
return params.node.canFlower;
},
cellRendererParams: { value: ' ' }, colId: 'PlusIcon', pinned: 'left', cellClass: 'center'
},
...
Listen to the rowGroupOpened event and set the row to selected:
// inside the ag-grid tag
(gridReady)="onGridReady($event)"
// inside the AppComponent class
onGroupOpened(event){
event.node.setSelected(true)
console.log(event)
}
plnkr example

how to remove first menu from ag-grid column menu

Is there an option to remove first menu from ag-grid column menu?
I mean the menu with 'pinSubMenu', 'valueAggSubMenu', 'autoSizeThis', etc.
I want to open the context menu and to see first the filter menu and second the columns visibility menu.
I tried to do this, but it still opens empty menu and I need to navigate to my filter menu:
function getMainMenuItems(params) {
var countryMenuItems = [];
var itemsToExclude = [
'separator', 'pinSubMenu', 'valueAggSubMenu', 'autoSizeThis', 'autoSizeAll', 'rowGroup', 'rowUnGroup',
'resetColumns', 'expandAll', 'contractAll','toolPanel'
];
params.defaultItems.forEach(function(item) {
if (itemsToExclude.indexOf(item) < 0) {
countryMenuItems.push(item);
}
});
return countryMenuItems;
}
Looks like you should be able to accomplish what you want to do within the gridOptions:
gridOptions = {
...
suppressMenuMainPanel: true,
...
}
You can also suppress any of the panels of the column menu:
gridOptions = {
...
suppressMenuMainPanel: true,
suppressMenuColumnPanel: true,
suppressMenuFilterPanel: true,
...
}
This is supposing that you are using the Enterprise version, which I assumed you were based on your usage of the getMainMenuItems function
You need to specify menuTabs in the colDef object:
{
headerName: "ID",
field: "id",
menuTabs: ['filterMenuTab','generalMenuTab','columnsMenuTab']
}
See more details here.

Extjs grid with multiselect feature to retrieve value of selected lists

Let's say I have a grid with multiselect option on, when user selects 4 lists and wants to get the values ( alerted on screen) how would I do that? And how would I disable buttons untill at least one list is selected?
All questions you've asked are answered many times already. Also there are good ExtJS examples on sencha.com. For example list view grid shows multiple select and editable grid with writable store shows button enable on click. But THE MOST important is documentation! Let me explain functionality on following code. Most of it is from list view example.
This grid gets JSON from list.php which has following structure
{"authors":[{"surname":"Autho1"},{"surname":"Autho2"}]}
And the grid:
Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.panel.*'
]);
Ext.onReady(function(){
// Here i've definned simple model with just one field
Ext.define('ImageModel', {
extend: 'Ext.data.Model',
fields: ['surname']
});
var store = Ext.create('Ext.data.JsonStore', {
model: 'ImageModel',
proxy: {
type: 'ajax',
url: 'list.php',
reader: {
type: 'json',
root: 'authors'
}
}
});
store.load();
var listView = Ext.create('Ext.grid.Panel', {
id: 'myPanel', // Notice unique ID of panel
width:425,
height:250,
collapsible:true,
renderTo: Ext.getBody(),
store: store,
multiSelect: true,
viewConfig: {
emptyText: 'No authors to display'
},
columns: [{
text: 'File',
flex: 50,
// dataIndex means which field from model to load in column
dataIndex: 'surname'
}],
dockedItems: [{
xtype: 'toolbar',
items: [{
// This button will log to console authors surname who are selected
// (show via firebug or in chrome js console for example)
text: 'Show selected',
handler: function() {
// Notice that i'm using getCmp(unique Id of my panel)
// to get panel regerence. I could also use
// this.up('toolbar').up('myPanel')
// see documentation for up() meaning
var selection = Ext.getCmp('myPanel').getSelectionModel().getSelection();
for (var i=0; i < selection.length; i++) {
console.log(selection[i].data.surname);
}
}
},{
text: 'Disabled btn',
id: 'myHiddenBtn', // Notice unique ID of my button
disabled: true // disabled by default
}]
}]
});
// Here i'm waiting for event which is fired
// by grid panel automatically when you click on
// any item of grid panel. Then I lookup
// my button via unique ID and set 'disabled' property to false
listView.on('itemclick', function(view, nodes){
Ext.getCmp('myHiddenBtn').setDisabled(false);
});
});
I didn't knew how to do this from top of my head, but I used documentation and the result works ;-). See Grid panel docs for more information.