Creating a more efficient repeating panel

Everyone who has worked with repeating panels knows that you must completely replace the .items property to change the contents, and the ways in which you have to change your code to adapt to that.

I’ve created a prototype of a component that allows you to organically work with its .items property, and have those changes reflected in the components without needing to do any additional work.

For example, you could do:

del self.rp.items[1]

and have the visual component reflecting that deleted item be removed automatically. You can also insert and append without resetting all the components.

This is all inspired by Stu’s excellent work on the Reactive module.

I have some questions, one of which will probably only be answerable by Anvil staff.

  1. Can a technique like this be retrofitted into Anvil’s repeating panel?

  2. If not, I can’t get the IDE integration for the new component working (where it shows a few sample rows in the repeating panel in the IDE). Does anyone have any idea how to accomplish that?

Here’s the clone link: Anvil | Login

This is the work of a few hours, so I can’t say everything works or is done the best way. But the core features seem to work well enough.

7 Likes

Still no IDE integration (if anyone knows how to get that working in the designer, I’d love to hear about it), but the panel now supports row template instances using remove_from_parent. It’ll automatically delete the corresponding item from the list.

This repeating panel is really cool! I don’t think it’s possible to get the IDE to show the items, if you set the items in the init function for a normal anvil repeating panel, those items also don’t appear in the designer.

Edit: And I think the reason for this is that with your component and the anvil repeating panel, they are all calling add_component for each item at run time, which doesn’t get displayed on the designer. This is also true of running addI_component directly in the form for any other component too. You can see this with the button I added to Form1 with add_component at the top of init

1 Like

Hmm…if I do the following in the EfficientRepeatingPanel init:

self.contents.add_component(Button(text="Hello init"))

The button does show up in the designer view. It looks like the init of the components of a form are run, so they can get rendered correctly in the designer.

But the init of the form itself is not run, which is why your button didn’t show up. And since the item template can’t be set until the form’s init, there doesn’t seem to be a way to get the sample rows showing in the designer.

Unless someone knows how to use the Form type property of a custom component. I just get back a string, which I can’t then use to instantiate an instance of the form template.

1 Like

Thanks to Stu over on Any progress on Form type property of custom components? , the IDE preview is now working.

In the EfficientRepeatingPanel.setup_template method, note there are two ways to get the preview working. One is not officially stable yet, while the other is. The not officially stable approach is the one that allows you to use the custom component as a dependency. Right now the stable option is uncommented, which means that to use the component you’d need to copy it and the ERPList code to your app.

If you’re using the component just to experiment, or in an app that isn’t ready for production, comment out the stable part and uncomment the get_form_constructor line. Then you’re safe to have the custom component in a dependency.

Edit: apparently the __import__ method is pretty fragile. It works in some apps and not others (possibly due to the age of the app?). get_form_constructor works in all cases.

1 Like

@jshaffstall this is really useful!

@stucork any chance of seeing this on the anvil repeating panels? :stuck_out_tongue:

1 Like