Data Grid Jump to last page load whole data

Does the jump to last page should load the whole data between first and last page?
It’s taking a while for 10 000 + rows.
Shouldn’t it only load the opened pages and not every single page?

    self.data_grid.jump_to_last_page()

The DataGrid does iterate all the elements, doesn’t skip to the desired page.

This old post talks about that problem.

I don’t know if things have changed since then. Maybe this will give you an idea to start experimenting, and maybe you will finally give us back a working solution :wink:

What?! So what is the point of having that? It will always be a problem for a big data.

I’m using custom buttons for controlling pagination and need to rework the whole atm. simple logic into something what sounds crazy…

First it will be necessary to make a check total rows > 1000-2000. Don’t skip to the last page and instead of that:

  • make an new server call with reverse order of items and…
  • reverse too the functions of the paginating buttons, so the user will start itearting from the fake “END”
    But in the reality it will be one more time from the beginning :slight_smile:.
  • Good that I’m saving the selected rows in a module variable, so I won’t lose which rows were selected. Sounds crazy, or I’m just crazy

Seriously this need to get some update.

I agree.

You could disable the standard navigation buttons and create your own. With your own you could always load the slice you need.

2 Likes

Ok, I’ve done some testing. Slicing cause to load the data too for the search iterator. So it’s not really an improvement.

But I have a really strange solution to the problem :slight_smile:.
I still need to find a way to show the showed “last” page in the right order. Now it’s too reversed. So each showed page in that mode need to be reordered.

Instruction

  1. add a hidden label to control the custom buttons
  2. create custom buttons for the pagination control
    image
  3. make changes to your server call function to react on jump to last page button differently if the total length of you list is for e.g. over 1500 rows.

How it works:

  • instead of jumping to the last page and loading the data. It make a database call to get the reverse order than it is now
  • with the hidden label, I control my if statement how the buttons will work
  • at the end it iterates from back but the number of page of pages should make you think otherwise :slight_smile:
  • I need only to find a way to reverse the order o the showed rows only (now it’s showing it reversed)

Custom button jump to the last page

  def last_page_click(self, **event_args):
    """This method is called when the button is clicked"""
    if self.total.text > 1500:
      database = anvil.server.call('get_sample_database_reverse')#modified function to force reverse ordert than it is now
      self.repeating_panel_assay.items = database#set new database with reverse order
      self.table_order.text = 'reverse'#to controll the rest of the custom pagination buttons
      self.page.text = self.pageof.text#set to last page#the counter page of pages to set the page to the last number
    else:#standard controll
      self.data_grid_assay.jump_to_last_page()
      self.page.text = int(self.data_grid_assay.get_page())+1

Custom button for previous page:

  def previous_click(self, **event_args):
    """This method is called when the button is clicked"""
    if self.table_order.text == 'reverse':
      self.data_grid_assay.next_page()
      self.page.text -= 1
      self.select_all.checked = False#reset check all to unselect
    else:
      self.data_grid_assay.previous_page()
      self.page.text = int(self.data_grid_assay.get_page())+1
      self.select_all.checked = False#reset check all to unselect

same changes need to be applied for next page and jumpt to the first page to reverse the process.

on the server side, the function that controls it need to take your query and how you order your table in consideration to work. I did for the test only a simple version without any additional query functions.

@anvil.server.callable
def get_sample_database_reverse():
  "fetch the basic data of samples"
  database = app_tables.sample_database.search(q.fetch_only("barcode", "study_id","name","status","matrix","ext_barcode",
                                                            "volume","order_number","comment",updated_by=q.fetch_only("email")),tables.order_by("barcode", ascending=False))
  return database

I would get your buttons to send the page number and page size to the server function, so the server function only returns the slice you need.

If you have sql access you can use offset and limit to get the exact slice you need, otherwise you can slice the iterator on the server side, much faster than slicing it on the client side. If you have a column with incremental unique values, you can use that with q.greater_than to skip to the page you need.

1 Like

The best solution would be really direct access. Sadly for now outside of my reach. Maybe some day in the future.

Calling server side all the time takes time, maybe with Enterprise it would be faster.
I will just accept it for now. You get really fast loading of each page, it’s great. I need only to add some check to that button: length <2000 jumping allowed, above notification and the jumping blocked. It’s rare case that someone need to jump to the last page. Fast switching is more important.

Yes, it does take time, but it takes less time than slicing on the client side. When you slice on the client side, you consume the iterator, which will trigger one server call every few (100?) items, so you end up with tons of (equivalent of) server calls that you didn’t even plan. So one server call is at worst as slow as getting the first page, but it’s usually much faster than going through an iterator on the client side.

Creating your own server side slicer instead, whether you do it with sql, with q.greater_than or by slicing the iterator on the server side, you will always have only one server call per user interaction.

You can get fancy and cache the slices on the client, so if the user clicks on next page, then on prev page, you get the cached page rather than executing another server call.

I would do this with the (omnipresent in my apps) routing module from Anvil Extras, and expose the page number and size in the url so that myapp/#?list=mylist&pagenumber=5&pagesize=20 would execute one server call to get items from 81-100. The paging buttons would use routing.set_url_hash to show the first/prev/next/last page and the router module would take care of caching the pages for you.