Running Python in the Browser
Client-side code interacts with your user interface by manipulating the Python objects that represent components. When components raise events, they call functions in your client-side code.
Client-side code interacts with server-side code by calling server functions.
User interface components in Anvil are Python objects.
Components have properties which are accessible as attributes. You can adjust a component’s appearance by setting a property (for example,
self.button_1.text = "Click me"). You can also read data from a component by reading properties (for example the
text property of a
TextBox component contains whatever text the user has entered in the box).
The properties of all Anvil’s built-in components can be found in the API documentation. (TODO link)
You can set initial values for a component’s properties by passing them as keyword arguments to the constructor (for example,
Components also raise events. For example, when a button is clicked, it raises the
When a component raises an event, it calls the event handler function for that event (if one has been set). This function will be passed a set of keyword arguments describing the event. Some of them are specific to the particular type of event (eg the
mouse_move event has
y arguments), but every event handler will also receive an argument called
sender, containing the component that raised the event.
Any event may supply more keyword arguments in future versions of Anvil. So, when you’re defining an event handler function, always include a catch-all
**event_args argument, which will receive a dictionary of any keyword arguments you haven’t explicitly handled. Here is an example:
def handle_click(**event_args): alert("The button got clicked!") self.button_1.set_event_handler('click', handle_click)
You may raise events on any component yourself, by calling the
raise_event() method. However, each component has a limited set of events, and
raise_event() will raise an exception if you do not raise a valid event for that type of component.
The exception are custom events, which are all events whose name begins with
"x-". So you can safely call
raise_event('x-foo') on any component.
Some actions can only be performed after a component is added to the web page in the browser. For example, a
Canvas component cannot discover the size of its drawing area until it is added to the page – so a form cannot usefully draw on a
Canvas during its
__init__ function. Instead, the drawing code must run when the form is added to the page.
To help handle these situations, all components have a
hide event, which trigger when the component is added to, or removed from, the page.
show event does not necessarily mean the component is visible to the eye - a component may be invisible, but its
show event still fires when it is added to the page. To be precise, these events trigger after the component is added to the browser’s HTML DOM.)
hide propagate across containers: If a component’s container is added to the page, it too is added to the page. A container’s
hide event is raised after all its children.
In Anvil, a Form combines code (a Python module, containing a class with the same name as the module) and a user interface (specified with a visual designer).
The code for your form is a Python module, which must define a class of the same name as the form (eg the
MyForm form must define a class called
MyForm), inheriting from the designer template.
When you design a form with the visual designer, this defines a template class. If your form is called
MyForm, the template class is
MyFormTemplate. The template inherits from a container component (
ColumnPanel for “Blank Panel” forms, or
HtmlTemplate for HTML-based forms).
When the form is initialised, before
__init__ is called, the template’s
__new__ method creates all the components specified in the visual designer, adds them to the form, and makes them available as attributes on the form object (eg
Like any component, your form should accept properties as keyword arguments to the
__init__ method. The default way to do this is to call
self.init_components(**p). This accepts any keyword arguments that specify properties of your form, and sets their values on your form. It then refreshes any data bindings.
Because all forms inherit from a container component, you can also set the properties of that container type on the form – for example,
init_components() will not set these inherited properties, as they are not intended to be used from outside.
At any point, a running Anvil application has one top-level component on the page. You can get a reference to it by calling
In each app, one form is nominated as the “startup form” (indicated by a lightning bolt icon). When the app starts, an instance of this form will be created (with no arguments) and set as the top-level component.
To set a new top-level component, pass a component to
open_form(). Alternatively, if you pass a string as the first argument to
open_form(), Anvil will instantiate the form of that name, with any extra arguments provided to
open_form(), then then open it as the top-level component. So the following two code snippets are equivalent:
open_form('MyForm', 'foo', bar=42)
from MyForm import MyForm f = MyForm('foo', bar=42) open_form(f)
Limits to Python in the browser
If you want to use a library that is not available in client code, write a server function that uses that library, then call it from the client.