I want to change the style of a row dynamically in ag-grid. What I'm trying to achieve is to change the background color of my ag-grid row if the row has been edited by the user.
cellValueChanged(event) {
//Add it only if the old value has changed
if (event.oldValue != event.newValue) {
// This will replace with latest edited value if it has been edited already
this.edittedRows[event.rowIndex.toString()] = event.data;
}
}
I'm keeping track of the edited row by listening to cellValueChanged event. I need to change the row style here.
I've looked into ag-grid documentation and found how to add row styles, row classes and row class rules but I could't find a way to add a style to a row dynamically when the user has changed something on it.
By using redrawRows I was able to achieve this.
First I added rowClassRules for my grid options like below
private initGrid() {
this.gridOptions.rowClassRules = {
'modified' : this.isEditedRow()
};
}
private isEditedRow() {
return (params) => {
return params.data.edited;
}
}
modified is my css class which has all the styles for an edited row.
Then in my row data I'm adding a new property edited.
And changed the cellValueChanged as below,
cellValueChanged(event) {
//Add it only if the old value has changed
if (event.oldValue != event.newValue) {
// This will replace with latest edited value if it has been edited already
// Setting edited flag to change the background
event.data.edited = true;
this.edittedRows[event.rowIndex.toString()] = event.data;
let row = this.gridApi.getDisplayedRowAtIndex(event.rowIndex);
this.gridApi.redrawRows({ rowNodes: [row] });
}
}
Find the documentation for redrawRows here.
Add below line in your CellValueChanged Function:
gridOptions.rowStyle = {background: 'coral'};
cellValueChanged(event) {
//Add it only if the old value has changed
if (event.oldValue != event.newValue) {
// This will replace with latest edited value if it has been edited already
this.edittedRows[event.rowIndex.toString()] = event.data;
gridOptions.rowStyle = {background: 'coral'};
}
}
Plunker - https://plnkr.co/edit/i1K3YXpGGgNEOU2JjZCf?p=preview
Related
I'm wondering how I can complete my cell renderer. The renderer adds a new row when clicking an icon, and removes it when clicked again. The problem is the invididual cell renderers row indexes do not change unless I hard refresh the entire grid (which then disables the state of the dropdown itself)
How can I complete this?
const insertIndex = params.rowIndex + 1;
this.eventListener = () => {
if (!this.eButton.classList.contains('open')) {
gridOptions.api.applyTransaction({add:[{step: this.dropdownValue, dropdownRow: true}], addIndex: insertIndex });
} else {
let rowData = [];
gridOptions.api.forEachNode(function (node) {
rowData.push(node);
});
let insertedRow = rowData[insertIndex];
gridOptions.api.applyTransaction({remove:[insertedRow.data]});
}
this.eButton.classList.toggle('open');
};
this.eButton.addEventListener('click', this.eventListener);
}
option 1: Hard refresh the grid, but I lose the 'open' status of the dropdown icon. How can i carry state over after a hard refresh?
option 2: Find a way that params.rowIndex is updated after applyTransaction.
Ive tried using the default rowGroup feature, however it hides all columns by default and I havent found a way to make it work the way I need.
The solution im after is a simple 'open/close' toggle for a single row underneath without affecting the other rows
I want to control row focus process. I need to show confirm dialog on row focus change in my table.
I tried to do this with rowClassRules property, but as I understood that functionality apply classes when table rendering, after that row classes stop changing
rowClassRules = {
'custom-row-focus': (params) => {
return params.data.id === this.currentSelectedItem.id
}
}
currentSelectedItem set's when I click on the row
Found an answer in docs
https://www.ag-grid.com/javascript-grid-row-styles/#refresh-of-styles
If you refresh a row, or a cell is updated due to editing, the rowStyle, rowClass and rowClassRules are all applied again.
So, when I'm clicking to the row I should make something like that:
onClicked($event: RowClickedEvent) {
$event.node.setData({...$event.data});
}
while creating an extension for vscode I got stuck in selection, now the problem is when I replace some range of textEditor through an api it replaces that range as well as make that range selected. For snippets this is a good idea but my extension requirement is not to select replaced text, I searched in api but did't find anything related to remove text selection (Selection occurs when the document is empty)
editor.edit((editBuilder)=>{ //editor is an object of active text editor
editBuilder.replace(textRange,text) // text = 'dummydummydummy'
}) //after this I got the following output
editor.edit(builder => {
builder.replace(selection, newStr);
})
// The edit call returns a promise. When that resolves you can set
// the selection otherwise you interfere with the edit itself.
// So use "then" to sure edit call is done;
.then(success => {
console.log("success:", success);
// Change the selection: start and end position of the new
// selection is same, so it is not to select replaced text;
var postion = editor.selection.end;
editor.selection = new vscode.Selection(postion, postion);
});
I believe that this is happening because the edit is being applied within the current selection. edit returns a promise that is resolved when the edit is applied, and you can use this to set the selection after the edit is successful:
editor.edit((editBuilder) => {
editBuilder.replace(textRange, text)
}).then(success => {
if (success) {
// make selection empty
editor.selection.active = editor.selection.anchor
}
})
let editor = vscode.window.activeTextEditor;
let selection = editor.selection;
editor.edit(builder => {
builder.replace(selection, newStr);
});
see: TextEditorEdit API Doc
Using Angular 4 (typescript), I have some code like below using ag-grid 12.0.2. All I'm trying to do is load my grid and automatically (programmatically) select the first row.
:
this.gridOptions = ....
suppressCellSelection = true;
rowSelection = 'single'
:
loadRowData() {
this.rowData = [];
// build the row data array...
this.gridOptions.api.setRowData(this.rowData);
let node = this.gridOptions.api.getRowNode(...);
// console logging here shows node holds the intended row
node.setSelected(true);
// console logging here shows node.selected == true
// None of these succeeded in highlighting the first row
this.gridOptions.api.redrawRows({ rowNodes: [node] });
this.gridOptions.api.redrawRows();
this.gridOptions.api.refreshCells({ rowNodes: [node], force: true });
First node is selected but the row refuses to highlight in the grid. Otherwise, row selection by mouse works just fine. This code pattern is identical to the sample code here: https://www.ag-grid.com/javascript-grid-refresh/#gsc.tab=0 but it does not work.
Sorry I am not allowed to post the actual code.
The onGridReady means the grid is ready but the data is not.
Use the onFirstDataRendered method:
<ag-grid-angular (firstDataRendered)="onFirstDataRendered($event)">
</ag-grid-angular>
onFirstDataRendered(params) {
this.gridApi.getDisplayedRowAtIndex(0).setSelected(true);
}
This will automatically select the top row in the grid.
I had a similar issue, and came to the conclusion that onGridReady() was called before the rows were loaded. Just because the grid is ready doesn't mean your rows are ready.(I'm using ag-grid community version 19) The solution is to setup your api event handlers after your data has loaded. For demonstration purposes, I'll use a simple setTimeout(), to ensure some duration of time has passed before I interact with the grid. In real life you'll want to use some callback that gets fired when your data is loaded.
My requirement was that the handler resizes the grid on window resize (not relevant to you), and that clicking or navigating to a cell highlights the entire row (relevant to you), and I also noticed that the row associated with the selected cell was not being highlighted.
setUpGridHandlers({api}){
setTimeout(()=>{
api.sizeColumnsToFit();
window.addEventListener("resize", function() {
setTimeout(function() {
api.sizeColumnsToFit();
});
});
api.addEventListener('cellFocused',({rowIndex})=>api.getDisplayedRowAtIndex(rowIndex).setSelected(true));
},5000);
}
Since you want to select the first row on page load, you can do onething in constructor. But your gridApi, should be initialized in OnGridReady($event) method
this.gridApi.forEachNode((node) => {
if (node.rowIndex === 0) {
node.setSelected(true);
}
It's setSelected(true) that does this.
We were using MasterDetail feature, its a nested grid and on expanding a row we needed to change the selection to expanded one.
Expanding a row was handled in
detailCellRendererParams: {
getDetailRowData: loadNestedData,
detailGridOptions: #nestedDetailGridOptionsFor('child'),
}
and withing loadNesteddata, we get params using we can select expanded row as
params.node.parent.setSelected(true)
Hope this helps.
I created a new tool in ContentTools that adds a static table (I don't want you to edit).
But being a static element doesn't maintain focus and I can not remove it when I click remove button.
I can do so that the table is not editable but can be removed if you click on it?
That's how I created the element:
new ContentEdit.Static('div', {'data-ce-moveable': true}, '<table><thead><tr><th>Foo head</th></tr></thead><tbody><tr><td>Foo body</td></tr></tbody></table>')
Thank you!
Static elements can't be interacted with for the most part (other elements can be dragged around them but that's about it). ContentEdit/Tools does allow you to restrict the some behaviour for elements but not being able to modify the content of a text element isn't one right now (though I think this might be a worthy addition).
However whilst there's no set way to do this at the moment here's an approach you can use that should provide the behaviour you describe (do let me know how you get on):
ContentEdit.Root.get().bind('mount', function(element) {
// We only care about `TableCell` elements
if (element.type() != 'TableCell') {
return;
}
// We only want to make the element read-only if the parent table has
// the `data-read-only` attribute.
var table = element.closest(function(node) {
return node.type() == 'Table';
});
if (table.attr('data-read-only') !== undefined) {
// Disable text editing for the table cell
element.tableCellText()._onKeyDown = function(ev) {
ev.preventDefault();
}
}
// Disable dragging of the table rows
var tableRow = element.closest(function(node) {
return node.type() == 'TableRow';
});
tableRow.can('drag', false);
tableRow.can('drop', false);
});