Issue
Some background:
All, let me explain a little bit about how we're using ag-grid here, and see if that helps us unearth an answer.
Our application utilizes Chrome's or Edge's local storage. This allows us to readily have available large quantities of data, but does present it's fair share of challenges.
For example, if a user updates the value of a field in their grid, we need that update to update in:
- the user's local storage
- the server
- push down the update to every other user in the user's organization
This sync happens and then finally we get to the bit of code below.
Also, we allow our users to update data in multiple places across the system, for example using the picture below:
A user can update the rows themselves (North, South, East and West Regions), OR they can click on Tower 12 South or Organization Alpha and update those names or other information in a modal.
NOTE: in this grid, Tower 12 South and Organization Alpha are indeed row groupings. They are also separate bits of data that can be manipulated elsewhere in the application. Essentially they are datum that relate to the row Data here.
The below bit of code fires when someone clicks on Say "Organization Alpha" and updates its name.
The main problem we are trying to solve is getting the grid to regroup and redraw correctly after someone updates the name on either Organization Alpha or Tower 12 South. We need to make the grid update the children underneath the row grouping that is updated, so that the row groupings can re-draw and we can display the proper name accordingly.
Before you recommend it: simply refreshing the clientsiderowmodel will not work. It refreshes with the old grid data. We must apply an update before doing any of that.
Update:
I have tried using both methods for applying a transaction, using node IDs, and using RowNode objects. Both ways produce the same result, even though the debugger shows I am legitimately passing good objects or ids.
Original post:
I am having a tough time understanding why in this particular instance of our application ag-grid doesn't want to allow row transactions on an array of Row Nodes, but will allow me to invoke the refreshCells method on the same array of row nodes.
The error I get (per node I am trying to update) is as follows:
clientSideNodeManager.js:181 ag-Grid: could not find row id=undefined, data item was not found for this id
Initially, I took this error at face value and thought that the rest of my code might be executing out of order, and the nodes I am passing as an argument might indeed be undefined. I took things a step further and simply set the call to applyTransaction() inside of a setTimeout to just double check that things were behaving accordingly. No luck there. I kicked off a debugger and used the console as well to just make sure things were firing in there required order. All seemed good so far.
Below is the bit of code that I am focusing on. Essentially I get a rowNode back from a different function, and need to update all of the leaf children underneath that row node. Simple enough.
My question is, why does the refreshCells method work, but the applyTransaction method does not work with the exact same rowNodes passed to it? I know that you cannot pass a row group to the applyTransaction method, which is why I simply need to update the children. Does anyone have an idea as to why this doesn't work?
//self=this by the way. Set earlier in function.
this.traverseTree(doc).then((res)=>{
console.log(res); //Shows the correct row group
console.log(res.allLeafChildren); //Shows all leaf children
setTimeout(() => {
if(res.allLeafChildren.length > 0) {
//Below function fires. Cells actually refresh
self.gridOptions.api.refreshCells({rowNodes: res.allLeafChildren, force: true});
//Will not apply transaction on same rowNodes. returns error above for each node
self.gridOptions.api.applyTransaction({update: res.allLeafChildren});
}
},10);
});
We are using Angular 10 and Ag-Grid version 24.0.0
Solution
What I ended up finding was the following:
According to Ag-Grid, there are 2 types of references. Direct node ID references, and node data object references.
For whatever reason, the Node ID Update method did not work. So in my question above I shifted to the object refence method of updating.
HOWEVER, it seems like the grid needed a NEW object to actually correctly know what rows we're trying to reference.
What ended up working for me was getting a fresh data set from local storage (indexedDB). I still don't know WHY using res.allLeafChildren didn't work, even though it was the same dataset.
this.traverseTree(doc).then((res) => {
// debugger;
let trans = [];
let childDocType = res.allLeafChildren[0].data.docType;
let projectID = res.allLeafChildren[0].data.exopp_equiprojects_id_c;
let optionFilter = {
filters: {
exopp_equiprojects_id_c: {
value: projectID,
operator: '=',
type: 'string'
}
}
};
let tempArr = [];
let delArr = [];
if(projectID === self.projectContextId){
//Here is where I'm getting the new dataset. Which returns the EXACT same data as res.allLeafChildren....
this.utils.getLocalDoc(childDocType, optionFilter).pipe(take(1)).toPromise().then((res) => {
Object.keys(res.docs).forEach(doc => {
tempArr.push(res.docs[doc]);
});
Object.keys(tempArr).forEach(doc => {
//If doc is deleted
if(tempArr[doc].deleted === 1 || tempArr[doc].deleted === '1') {
delArr.push(tempArr[doc]);
} else {
trans.push(tempArr[doc]);
}
});
if(delArr.length > 0) self.gridOptions.api.applyTransactionAsync({remove: delArr});
// debugger;
self.gridOptions.api.applyTransactionAsync({update: trans});
self.gridOptions.api.refreshCells({rowNodes: trans, force: true});
});
}
});
Now that it dawns on me, the other thing I could do would be seeing if using something like JSON.parse(JSON.stringify(res.allLeafChildren)) and seeing if that also solves the problem/ saves me from having to query indexedDb.
Anyway, just be aware of this problem. This question and answer lies inside of a different grid function that communicates with data coordinated from GraphQL
Answered By - Willie

0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.