Live Chat

We'll need to share your messages (and your email address if you're logged in) with our live chat provider, Drift. Here's their privacy policy.

If you don't want to do this, you can email us instead at contact@anvil.works.

Creating Custom Components

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.)

Forms are Components

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.

A Form with another Form dropped into it twice.

All Forms can be dragged-and-dropped into other Forms from the App Browser.

You can take this one step further and actually add Forms to the Toolbox as Custom Components.

Making a Form appear in the Toolbox

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:

Select ‘Use as component’ from this dropdown menu.

Select ‘Use as component’ from this dropdown 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.

This is the dialog you’ll see when you select ‘Use as component’.

This is the dialog you’ll see when you select ‘Use as component’.

Custom Properties

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

Initialisation

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 init_components().

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:

Configuring the details of a Custom Component property.

Configuring the details of a Custom Component property.

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.

Custom Events

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.

Configuring events

You can expand an event to configure its details:

Configuring an event

Configuring an event

Event parameters

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:

Autocompleting event parameters

Autocompleting event parameters

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 “click”.