General newbie question on OOP approach in Anvil

Hello, I am new to OOP and Python but I have 15 years + in C programming in a former life, so kind of a newbie as far as OOP is concerned… I think I understand OOP theoretically (somewhat) but I am finding the procedural to OOP jump difficult in practice…
One thing that I am trying to understand is why am I editing a Class directly, e.g. “class Form1(Form1Template):” surely the class was created by you folk and I should be passing parameters into my own instance of that class, not messing with the class directly? Not sure if this sounds like a dumb question but its been bugging me for weeks… I though the class is a ‘template’ and the instance is my version of that template filled out i.e. the object instance which is then executed? right?
Look forward to your reply. Thanks

1 Like

To tell your instances

  1. how you want them to behave, e.g., what to do when someone clicks the “Save” button you added in the IDE, and
  2. what additional information they will keep on-hand (as member variables) in order to support such behavior, e.g., the specific values to be saved, and where to save them.
1 Like

One approach would be for Anvil to provide a Form class that allows to add buttons, labels, etc.

Another approach would be for Anvil to provide a FormTemplate class able to manage the basics of being a form. Then leave it to you to create the class MyForm derived from FormTemplate and add more members to it. The resulting MyForm will be a class with all the basic features derived from FormTemplate, plus anything you added to it.

If you look at how each form is defined, you will find:

from ._anvil_designer import MyFormTemplate
class MyForm(MyFormTemplate):

This means that Anvil will create a template class under the hood called MyFormTemplate and setup an empty class MyForm where you can add all your methods. Perhaps under under the hood MyFormTemplate is derived from a more generic FormTemplate, but we don’t care. All we care is that MyForm has all the methods and properties derived from MyFormTemplate plus all the ones that you will be adding.

You can create a form that takes arguments in the constructor and add your own members, something like:

class MyForm(MyFormTemplate):
    def __init__(self, generating_pdf=False, default_settings=None, **properties):
        self.generating_pdf = generating_pdf
        self.default_settings = default_settings or {}

    def show_only_third_button(self):
        self.button_1.visible = self.button_2.visible = False
        self.button_3.visible = True

At this point you can use both MyForm.add_components() defined in MyFormTemplate and MyForm.show_only_third_button() defined by you.

And use it either in an alert or to generate a PDF:

    # on the client
    alert(MyForm())
    
    # on a server module
    settings = {<something here>}
    anvil.pdf.render_form('MyForm', generating_pdf=True, default_settings=settings)

If you think functional, the C way, you would need functions able to do stuff with the form template MyForm.

If you think OO, the Python way, you teach the class how to do stuff, you instantiate an object of that class, and tell that object what to do.

3 Likes

Thanks for your detailed response and describing inheritance from FormTemplate class to MyForm class - I suppose when we hit run, the anvil engine creates the required instances for execution…

You can create a new instance of a form yourself, for example when you want to show the form inside an alert, with alert(MyForm()), or when you want to add it to a container in an existing form, with self.column_panel_1.add_component(MyForm()).

And in some cases Anvil will do that automatically.

You could also do silly things like:

f1 = MyForm()
f2 = MyForm2()
f3 = MyForm()
alert(f1)
alert(f2)
alert(f3)

where f1 and f3 are two distinct instances of MyForm.

1 Like

Thank you so much. Will try these out :smile: