Having a infinite scroll (with new items loaded by remote calls) together with collection repeat and items of different size, I have an issue that after new batch of item is renedered, the scrollbar "jumps" to the middle, or to explain it other way around, it is not on the bottom where it should be (on the button but moved a bit back to accomodate for the new items).
The most probable issue is that
this.$scope.$broadcast('scroll.infiniteScrollComplete');
is called BEFORE the items are added to the array / rendered.
One easy way to do this is if items are added as a result of a promise, but $broadcast is done before the promise is completed.
solved this by setting item-render-buffer property of collection-repeat
<div collection-repeat="business in businesses" item-height="120px" item-render-buffer="10"></div>
Related
I would like some help into speeding up the process of filtering a long list of list items and viewing them on a ListView.
My app has a search bar, a ListView and a very long list of strings to choose from.
When the user enter a search term, the ListView is updated with every key stroke and filter out the irrelevant items.
Sorting itself takes a few milliseconds, but updating the ListView afterwards with the new filter-event takes a long time (20 seconds easy, if only a single character has been entered as search criteria)
I believe the time is spent on inflating a large number of ViewCells every time the filtered list updates.
Do any of you know how to speed up the process? I thought the way it could work was to have a very limited number of ViewCells (like 10 or 20) and then have them update and just show a selection of the filtered list. Scrolling would to be reusing the top/bottom one, update the content and put it back on the bottom/top - but I have not been able to wrap my head around how to do this.
Maybe it is the wrong approach and you know a better way?
I just had a similar problem that my list with just 20 elements would search extremely slow. Maybe your problem is similar. Sadly you didn't post any code. I had something like this:
List l = originalItems.Where((i) => i.Name.Contains(filterText));
listView.ItemsSource = l;
And I could not understand why this would be so slow. I found a different approach with more overhead that for some reason is faster and more responsive and overall feels better for the user. My ListView always has an ObservableCollection as ItemsSource. When I filter I calculate the difference to this ObservableCollection (the extra items and the removed items) and then remove or add accordingly. This avoids replacing the ItemsSource property which seems to be too harsh on the ListView.
//property of the class
ObservableCollection<FlightListItem> listViewItems;
// ....
//somewhere at initialization
listView.ItemsSoure = listViewItems;
// ....
//in the filter method:
List l = originalItems.Where((i) => i.Name.Contains(filterText));
IEnumerable itemsToAdd = l.Except(listViewItems).ToList();
IEnumerable itemsToRemove = listViewItems.Except(l).ToList();
listView.BeginRefresh();
foreach (FlightListItem item in removes)
listViewItems.Remove(item);
foreach (FlightListItem item in added)
listViewItems.Add(item);
listView.EndRefresh();
Notes:
removing the listView.BeginRefresh() and EndRefresh() did not seem to impact performance, but it seems the right thing to call them here.
We need to call ToList() on the itemsToAdd and itemsToRemove even though we only need IEnumerables! This is because Except is a lazy operation and will otherwise only be evaluated during the for loop. However during the for loop one of the parameters to Except changes which leads to an IllegalArgumentException due to modifying an IEnumerable while going over it.
If anyone knows a good filterable observable collection that would probably be a nicer solution.
is it possible to configure agGrid grouping so that it behaves like an accordion i.e. only one group can be expanded and when opening new group previously opened is closed?
Not sure if this answers your question, but I am sure this might be the only direction you'll have.
There is a method provided on gridApi - onGroupExpandedOrCollapsed
So I think (again, need to check) that this function would be called as its name suggests, and you can collapse the other rows (whichever is opened) and achieve your functionality.
Be cautious while using this as there is comment given by ag-grid
we don't really want the user calling this if one one rowNode was
expanded, instead they should be calling rowNode.setExpanded(boolean)
- this way we do a 'keepRenderedRows=false' so that the whole grid gets refreshed again - otherwise the row with the rowNodes that were
changed won't get updated, and thus the expand icon in the group cell
won't get 'opened' or 'closed'.
I have a page with many elements (forms and tables)
When I want add a row in a table I scroll the page to the table, I press a button to add a row, edit the info in a popup and press OK.
Then I insert the new row in the model and refresh() the model.
At this point the page auto scroll at the top, but I don't want this behavior!
I want that the page stay in the same Y position!
I see that sap.m.page has scrollTo function https://openui5.hana.ondemand.com/docs/api/symbols/sap.m.Page.html#scrollTo
but I don't know how take the position before the refresh()
The Page does unfortunately not have an API to get the current scroll position, but the idea is a good one we consider.
As a workaround you could access some private method of the Page - but only if you accept the risk that it breaks with a future version of UI5:
page.getScrollDelegate().getScrollTop()
To make it safer you should verify both methods exist before calling them and also check the returned value for plausibility. Then you are pretty safe that in the worst case it will again scroll to the top in some future UI5 version.
you have to fill the iTime parameter in scrollTo function - e.g. srollTo(100, 1) - then it works
using 0 for iTime does not work
I am using GWT 2.4's new DataGrid in a project. I configured the DataGrid with a pagesize of 50.
The available screen is not big enough to display all items and thus a vertical scrollbar is shown (this is actually the main purpose for using a DataGrid in the first place).
I attached a SingleSelectionModel to the DataGrid in order to be able to select items.
This works fine so far.
However I also have another widget with which the user can interact. Based on that user action a item from the DataGrid should be selected.
Sometimes the selected item is not in the visible screen region and the user has to scroll down in the DataGrid to see it.
Is there any way to automatically or manually scroll down, so that the selected item is visible?
I checked the JavaDocs of the DataGrid and found no appropriate method or function for doing that.
Don't know if this works, but you could try to get the row element for the selection and use the scrollIntoView Method.
Example Code:
dataGrid.getRowElement(INDEX_OF_SELECTED_ITEM).scrollIntoView();
The answer above works pretty well, though if the grid is wider than your window and has a horizontal scroll bar, it also scrolls all the way to the right which is pretty annoying. I was able to get it to scroll down and stay scrolled left by getting the first cell in the selected row and then having it scroll that into view.
dataGrid.getRowElement(dataGrid.getVisibleItems().indexOf(object)).getCells().getItem(0).scrollIntoView();
Don't have time to try it out, but DataGrid implements the interface HasRows, and HasRows has, among other things, a method called setVisibleRange. You just need to figure out the row number of the item that you want to focus on, and then set the visible range from that number n to n+50. That way the DataGrid will reset to put that item at the top (or near the top if it is in the last 50 elements of the list backing the DataGrid). Don't forget to redraw your DataGrid.
Have you already looked at this? If so, I'd be surprised that it didn't work.
Oh, and since this is one widget talking to another, you probably have some messaging set up and some message handlers so that when the user interacts with that second widget and "selects" the item, the message fires on the EventBus and a handler for that message fixes up the DataGrid along the lines I've described. I think you'll have to do this wiring yourself.
My solution, a little better:
dataGrid.getRow(model).scrollIntoView();
I got a Out of bounds exception doing the above.
I solved it getting the ScrollPanel in the DataGrid and used .scrollToTop() and so on on the ScrollPanel. However, to access the ScrollPanel in the DataGrid I had to use this comment:
http://code.google.com/p/google-web-toolkit/issues/detail?id=6865
As Kem pointed out, it's annoying the "scrollToRight" effect after the scrollIntoView. After me, Kem's solution gives a better behaviour than the base one as usually the first columns in a table are the more meaningful.
I improved a bit his approach, which scrolls horizontally to the first column of the row we want to be visible, by calculating the first visible column on the left before applying the scroll and then scrolling to it.
A final note: Columns absolute left is tested against "51". This is a value I found "experimentally" by looking the JS values in the browser's developer tool, I think it depends on the table's style, you may need to change/calculate it.
Below the code:
public void scrollIntoView(T next) {
int index = datagrid.getVisibleItems().indexOf(next);
NodeList<TableCellElement> cells = datagrid.getRowElement(index).getCells();
int firstVisibleIndex = -1;
for(int i=0; i<cells.getLength() && firstVisibleIndex<0;i++)
if(UIObject.isVisible(cells.getItem(i)) && (cells.getItem(i).getAbsoluteLeft() > 51) && (cells.getItem(i).getAbsoluteTop() > 0))
firstVisibleIndex = i;
cells.getItem(firstVisibleIndex>=0? firstVisibleIndex : 0).scrollIntoView();
}
I am using the ScrolledComposite for a existing control(with many children) based on the method2 mentioned here :http://www.placelab.org/toolkit/doc/javadoc/org/placelab/util/swt/SwtScrolledComposite.html
The only change is instead of creating a new shell & display I am using the existing control's parent.
I am seeing the scroll bars as expected but the existing control/content is displayed form the centre & not from the start. The first half(vertically split) of the layout is empty & the actual control/content gets displayed in the right-half.
I checked bounds, Origin, size etc. they seem to be fine.
screenshot putup here :http://img818.imageshack.us/i/contentstartsfrommiddle.jpg
Any clues
Thanks in advance
Did you delete the Composite c1? maybe that is in the left side.
You could also provide what is exactly your change to the code.