Ag-Grid how to start loading records from the 500th? - ag-grid

I have a Ag-grid configured to work in infinity scroll
In the documentation, i found this example, which shows how to make a jump to the 500th record
But I'm looking for a way to start loading the grid directly to the 500th record
Maybe there is a property to set in the grid?
Or should I put in some event this code:
jumpTo500() {
if (this.gridApi.getInfiniteRowCount() < 501) {
this.gridApi.setInfiniteRowCount(501, false);
}
this.gridApi.ensureIndexVisible(500);
}
Which?

you can use ensureIndexVisible on onGridReady stage:
onGridReady(params) {
this.gridApi = params.api;
this.gridColumnApi = params.columnApi;
this.gridApi.ensureIndexVisible(499); <--- add this line
Note : this.gridApi.ensureIndexVisible(numberValue) number value should be less than infiniteInitialRowCount atleast for 1
infiniteInitialRowCount = 1000 - initial config
this.gridApi.ensureIndexVisible(999) - max
Update: another possible way via firstDataRendered
firstDataRendered Fired the first time data is rendered into the grid.
(firstDataRendered)="firstDataRendered($event)"
...
firstDataRendered(){
this.gridApi.ensureIndexVisible(499);
}

The ag-grid has a bug in infinity scroll mode
They are working to fix the bug
The solution proposed here is the best workaround I have found so far
But it does not permanently resolve the performance bug
In fact, looking in the logs you can see that the program always makes a first unnecessary request, to view the first 100 records
Only then, the workaround requires the correct records from 400 to 500

Related

Filtering on ag-grid serverside not setting start row to 0 and end row to 100

Really need help on this, please.
Brief: I have implemented ag-grid serverside mode with partial store for lazy loading.
Problem Scenario : ServerSide mode, what happens is as you scroll more data is loaded, in terms of ag-grid more row blocks are loaded.
Lets say block size is 100 rows.
I scrolled 5-6 times, 5-6 request went to the server , loaded the data into the grid using success callback of getRows method in ServerSideDataSource Implementation.
You are currently viewing 500th-600th row in your viewport(the last request that went to server).
If you go and apply a fresh/change-existing filter on a column, the getRows method will get called but with request params having startRow 500 and endRow 600(rowBlock you are currently viewing).
This is the issue. I want that to be 0 and 100 respectively as you generally implement server-side filtering. It should be a fresh request to server right. ag-grid should recognise a new filter got applied so dump the existing rows on the grid send fresh request to server with 0 and 100 values.
This start and end row values are fine when you have already loaded data with filter applied till 500 and scrolling to load 500-600. But when the filter is first applied/ freshly applied(change from existing filter/ newly applied) you need the start and end rows to be 0 and 100 right. Help!!
Hi i came across this question while searching for this exact problem, looking around to the docs and couldn't find solution there. It's happening after they introduce serverSideStoreType: "partial | full".
my current workaround for this is to updating params.request.filterModel on your getRows datasource, if detect any changes on filterModel
getRows: function (params) {
//update startRow to 0 then detect changes
if(grid.filterModel != JSON.stringify(params.request.filterModel) ){
params.request.startRow = 0;
}
grid.filterModel = JSON.stringify(params.request.filterModel);
I got a method,after filter changed grid will be scrolled to the first row.
Angular :
filterChanged(params: FilterChangedEvent): void {
this.gridApi.ensureIndexVisible(0,null);
}
Javascript :
filterChanged(params) {
gridOptions.api.ensureIndexVisible(0,null);
}

Wait for backend service response before making changes to ag-grid table

I am using ag-grid/ag-grid-angular to provide an editable grid of data backed by a database. When a user edits a cell I want to be able to post the update to the backend service and if the request is successful update the grid and if not undo the user's changes and show an error.
I have approached this problem from a couple different angles but have yet to find the solution that meets all my requirements and am also curious about what the best practice would be to implement this kind of functionality.
My first thought was to leverage the cellValueChanged event. With this approach I can see the old and new values and then make a call to my service to update the database. If the request is successful then everything is great and works as expected. However, if the request fails for some reason then I need to be able to undo the user's changes. Since I have access to the old value I can easily do something like event.node.setDataValue(event.column, event.oldValue) to revert the user's changes. However, since I am updating the grid again this actually triggers the cellValueChanged event a second time. I have no way of knowing that this is the result of undoing the user's changes so I unnecessarily make a call to my service again to update the data even though the original request was never successful in updating the data.
I have also tried using a custom cell editor to get in between when the user is finished editing a cell and when the grid is actually updated. However, it appears that there is no way to integrate an async method in any of these classes to be able to wait for a response from the server to decide whether or not to actually apply the user's changes. E.g.
isCancelBeforeStart(): boolean {
this.service.updateData(event.data).subscribe(() => {
return false;
}, error => {
return true;
});
}
does not work because this method is synchronous and I need to be able to wait for a response from my service before deciding whether to cancel the edit or not.
Is there something I am missing or not taking in to account? Or another way to approach this problem to get my intended functionality? I realize this could be handled much easier with dedicated edit/save buttons but I am ideally looking for an interactive grid that is saving the changes to the backend as the user is making changes and providing feedback in cases where something went wrong.
Any help/feedback is greatly appreciated!
I understand what you are trying to do, and I think that the best approach is going to be to use a "valueSetter" function on each of your editable columns.
With a valueSetter, the grid's value will not be directly updated - you will have to update your bound data to have it reflected in the grid.
When the valueSetter is called by the grid at the end of the edit, you'll probably want to record the original value somehow, update your bound data (so that the grid will reflect the change), and then kick off the back-end save, and return immediately from the valueSetter function.
(It's important to return immediately from the valueSetter function to keep the grid responsive. Since the valueSetter call from the grid is synchronous, if you try to wait for the server response, you're going to lock up the grid while you're waiting.)
Then, if the back-end update succeeds, there's nothing to do, and if it fails, you can update your bound data to reflect the original value.
With this method, you won't have the problem of listening for the cellValueChanged event.
The one issue that you might have to deal with is what to do if the user changes the cell value, and then changes it again before the first back-end save returns.
onCellValueChanged: (event) => {
if (event.oldValue === event.newValue) {
return;
}
try {
// apiUpdate(event.data)
}
catch {
event.node.data[event.colDef.Field] = event.oldValue;
event.node.setDataValue(event.column, event.oldValue);
}
}
By changing the value back on node.data first, when setDataValue() triggers the change event again, oldValue and newValue are actually the same now and the function returns, avoiding the rather slow infinite loop.
I think it's because you change the data behind the scenes directly without agGrid noticing with node.data = , then make a change that agGrid recognises and rerenders the cell by calling setDataValue. Thereby tricking agGrid into behaving.
I would suggest a slightly better approach than StangerString, but to credit him the idea came from his approach. Rather than using a test of the oldValue/newValue and allowing the event to be called twice, you can go around the change detection by doing the following.
event.node.data[event.colDef.field] = event.oldValue;
event.api.refreshCells({ rowNodes: [event.node], columns: [event.column.colId] });
What that does is sets the data directly in the data store used by aggrid, then you tell it to refresh that grid. That will prevent the onCellValueChanged event from having to be called again.
(if you arent using colIds you can use the field or pass the whole column, I think any of them work)

UICollectionView Not Redrawing

I have a pretty simple UICollectionView that for some reason does not reloadData() as I would expect after a filter is applied. I am getting the right values into the filtered array, but I am getting rogue cells in the collection view that do not clear until scrolled - dequeued.
In some cases it works fine. I've yet to understand the condition in which it doesn't.
I have an array of objects master, and an array that is used to hold values that are filtered from that master array, ie:
hourly = hourlyMaster.filter { $0.forecastDateTime >= minDate }`
The cellForItemAt functionality all works fine. I just want the view to redraw after I apply the filter to the array. Apparently,
hourlyCollectionView.reloadData()
immediately following the filter is not getting it done. I'm sure there is something easy I'm missing here. ANY ideas are greatly appreciated.
Try putting the reloadData() in the hourly array's didSet to always reload the collection view when the data source is updated. You may be calling reloadData() faster than the filter function is executing.
var hourly: [Date] = [] {
didSet {
hourlyCollectionView.reloadData()
}
}
Never did get a viable solution or figure this out. Found a radar from a little while back... here.
The workaround is simply to use yourCollectionView.reloadSections()
That solved my issue. I'm not absolutely certain if there is another variable in my circumstance that caused this issue, but nothing else worked.

DevExpress VerticalGrid in unbound mode with MultiRecordLayout

EDIT: As it turns out, the grid does not support unbound mode in MultiRecordView layout.
I will try to ask this question a different way since my last one was downvoted without comment, so I don't know what the downvoter was objecting to.
I've worked quite a lot with the DevExpress VerticalGrid in unbound mode in SingleRecordView. We use it in all of our desktop applications that involve lots of data-entry. All data-entry forms are consistent in look-and-feel and so user training is minimal. I think it is a great control.
However, I don't understand how to use it in unbound mode in MultiRecordView layout. I cannot even figure out how to populate the unbound grid with the data for several records. In SingleRecord layout, I use the RowsIterator to move data from my data object in memory into the corresponding row/cell in the VerticalGrid's single record.
But in MultiRecordView layout, I can't figure out how to add the second record and the third record, etc etc, and position the current record pointer so that the RowsIterator is working with the rows of the correct record.
A small code snippet, showing how to move the current record pointer when adding the second and subsequent records in MultiRecordView, would be very helpful.
I've tried AddNewRecord() and setting the FocusedRecord but without success:
for (int i = 0; i < MyTable.Rows.Count; i++)
{
vGridControl1.AddNewRecord();
vGridControl1.FocusedRecord = i;
vGridControl1.RowsIterator.DoOperation(new DataPuller(MyTable.Rows[i]));
}
and here's a relevant snippet from my DataPuller object:
public override void Execute(DevExpress.XtraVerticalGrid.Rows.BaseRow brow)
{
//<snip>
if (brow is DevExpress.XtraVerticalGrid.Rows.EditorRow)
{
string fieldname = brow.Properties.FieldName;
if (table.Columns.Contains(fieldname))
{
brow.Properties.Value = (table[fieldname] == DBNull.Value) ? null : table[fieldname];
}
}
//<snip>
}
The vertical grid doesn't support unbound mode when in MultiRecordView layout.

Get max axis value from MS Charts C#.NET

I banged and banged my head on this one for a while and I figured someone else may have this problem down the line. I'm posting my full issue and resolution to those who come later, and to offer a spot for any improvements/simplifications if anyone finds one.
Issue was I am trying to paint VerticalLineAnnotations on my ChartArea. I do not want to anchor it to any data points but merely anchor it to an X axis based on which ChartArea I send in. In my annotation constructor I was trying to set AnchorX.
double maxdate = chart.ChartAreas[0].AxisX.Maximum;
double mindate = chart.ChartAreas[0].AxisX.Minimum;
//use inputdata to find where relative spot is.
if(DateTime.TryParse(date, out ddate)) {
AnchorX = (ddate.ToOADate()) / (maxdate - mindate);
}
I kept getting the mins and maxs to return as NaN, which I found out means the ChartArea will manage itself and set its own max/mins. This was all pre-painting.
I tried post painting but then everytime it painted, it would add annotation, then do postpaint again and infinite loop.
I finally found an event that lets me do this. The Customize() event solved this issue.
private void chart_Customize(object sender, EventArgs e) {
PaintAnnotations();
}
Now immediately before the painting happens, data seems to be loaded and max and mins are already set by this point and I can get values back in the code from above.
Hope this can save someone the hours that I lost!