How to add 'scroll' event handler to RepeatingPanel?

Hello,

I am wondering if there is a way to add an “on-scroll” event to a RepeatingPanel?

For some context, I have several horizontal repeating panels and want to lazy load the panel’s items (images). I have tried setting the images’ loading property to “lazy” in the following way:

class item_template(item_templateTemplate):
  def __init__(self, **properties):
    # Set Form properties and Data Bindings.
    self.init_components(**properties)

    # Get DOM element and add set the loading attribute to "lazy"
    image_component = anvil.js.get_dom_node(self.item_image)
    img_element = image_component.firstChild
    img_element.loading = 'lazy'

    self.item_image.source = self.item['src']

This does work for the vertical repeaters but not for the horizontal repeaters. I.e., all the RepeatingPanel’s items are loaded when the panel itself is scrolled into view (even though most items are outside the panel’s horizontal boundaries).

So I was thinking about writing the lazy logic manually by checking whether an item is scrolled into view and setting its source at that point in time. Something like this

class MyForm(MyFormTemplate):

    def __init__(self, **properties):
        self.init_components(**properties)
        self.repeating_panel_1.set_event_handler('scroll', self.lazy_load_images)

    def lazy_load_images(self, **event_args):
        panel = self.repeating_panel_1  
        panel_items = panel.get_components()  # Get all components inside the panel
        images = [item.item_image for item in panel_items]

        for image in images:
            if image.visible and image.data_src and self.is_image_in_viewport(image):
                image.source = image.data_src
                image.data_src = None  # Remove data-src attribute to prevent re-loading

    def is_image_in_viewport(self, image):
        image_component = anvil.js.get_dom_node(image)
        rect = image_component.get_bounding_rect()
        return rect.left < Window().innerWidth and rect.right >= 0

However, the scroll event is not implemented for repeating panels and I am wondering if there is a straightforward way to do this.

This does not directly answer your question, but it could give you some idea: with the AutoScroll custom component I have used a linear panel rather than a repeating panel, so I have the control of what and when is loaded.

1 Like

Thanks Stefano!

Actually I was mistaken, it seems the lazy loading is also working for my horizontal repeaters!

I was loading the same images in a different repeating panel which didn’t have lazy loading, which in turn made the images load instantly for the repeaters that DID have lazy loading as well. This is what made me think it is not working.

While my current problem is solved, I think that a scroll event would be useful in general so I will make a seperate feature request for it.

You can use the augment module of Anvil Extras to add any javascript event to your app.

I just checked and I noticed that I haven’t used it in the AutoScroll custom component, I think because I had to use some jquery to find the element with the scrollbar to make it more generic.

1 Like