You can create your own component types in Anvil by designating Forms as ‘custom components’. You can give them custom properties and events.
This allows you to create components that are composites of many Anvil components from the Toolbox. (By using Custom HTML Forms, you can also design components using HTML, and combine Anvil components and HTML.)
Anvil Forms are just components - you can create them in code by importing the appropriate module and calling the constructor, just as you would do for any other component.
In Code view of the Anvil Editor, a Form is represented by a Python module. This module defines a class with the same name as the Form.
For example, if you have a form called MyWidget then on any other form you can
import MyWidget and then add an instance of your widget to your form. For example:
from MyWidget import MyWidget # When the button is clicked, add an instance of the 'MyWidget' to this form: def button_1_click(self, **kwargs): self.add_component(MyWidget())
You can also drag-and-drop Forms directly from the App Browser. Just click on a Form’s name in the App Browser and drag it into the Design View to drop it onto another Form.
You can take this one step further and actually add Forms to the Toolbox as Custom Components.
You can also make your
MyWidget form appear as a custom component in the Toolbox. To do this, first select the
MyWidget form in the App Browser, then choose “Use as component” from the drop-down menu:
Now tick “Make this Form available as a component”. This will cause it to show up in the Toolbox under “Custom Components”.
In this dialog box you can also configure any custom properties and events your component should have. These will show up in the Properties Panel in the Design view of the Form Editor when you drop an instance of the component onto another Form.
Configuring a custom property for your Form creates an attribute on your form (eg
self.initial_text), which starts out with the specified default value. (To be precise, custom properties are implemented as data descriptors.)
Running code when properties are updated
Sometimes you will want to update your custom component when the value of a property is set. To do that, you can use Python’s standard Property Descriptors to run code when your property is set.
This lets you define your own getter and setter methods for the property attribute, as in the example below:
class MyForm(MyFormTemplate): def __init__(self, **properties): # Values of custom properties will be passed in as keyword arguments to # the __init__ method. When we call init_components(), these values will # be set as attributes, which in this case will trigger the setter below. self.init_components(**properties) # Use property descriptors to implement our own getter and setter for the # my_prop attribute. @property def my_prop(self): print("Getting my_prop: %s" % self._prop) return self._my_prop @my_prop.setter def my_prop(self, value): print("Setting my_prop: %s" % value) self._my_prop = value
Property values from the designer are supplied as keyword arguments to the Form’s constructor. When you call
init_components() from your Form’s
__init__ method, it updates your custom properties with these values.
So if there is anything you need to initialise before your property setter executes, you should do it before calling
Properties and Data Bindings
In the Custom Component configuration dialog, you can configure more details about each property, including some documentation text and its Data Binding behaviour:
Users of your Custom Component can make use of normal Data Bindings to set its properties.
For each property, you can choose whether it supports Data Binding write-back. For properties which support write-back, you can also choose which event(s) should trigger that write-back.
Shadowing property names
It is possible to create a custom property with the same name as a property of the container your form inherits from. This “shadows” the inherited property, and reading or writing this property does not affect the inherited container.
For example, if your Form is a “Blank Panel” Form, it inherits from
ColumnPanel, and inherits a property called
background. If you define a custom property called
background, then you’ve shadowed the parent property: When you set
self.background, it will not affect the background colour of your panel.
Users of your component can bind event handlers from the visual designer, or from code by calling
set_event_handler() on an instance of your component.
To raise these events, call
self.raise_event('my_event_name') in the usual way, passing event parameters as keyword arguments.
You can expand an event to configure its details:
This documents what parameters users of your components should expect for each event. When you’re using this custom component, and create an event handler for this event in the visual designer, these parameters will be automatically included in the created function:
The default event
If you configure an event as the default event for a component, then double-clicking an instance of the component in the designer will automatically jump to the event handler for that event. For example, the default event of the built-in Anvil
Button component is “