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. You can find a list of every built-in component in Anvil in the Anvil API Reference.
You’re not restricted to the components built into Anvil. You can make your own custom components.
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 Reference.
You can set initial values for a component’s properties by passing them as keyword arguments to the constructor (for example,
Components can also raise events. For example, when a button is clicked, it raises the
You can see what events a component raises in the visual designer. This example is for a Button component:
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 some built-in arguments:
senderis the component that raised the event.
event_nameis the name of the event, as a string.
You can set event handlers in the visual designer, or you can do it in code by calling the component’s
set_event_handler() method. Here is an example of doing it in code:
def handle_click(**event_args): alert("The button got clicked!") self.button_1.set_event_handler('click', handle_click)
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. This is also good for soaking up the
event_name parameters, which you’re not usually interested in.
Raising events from code
You may raise events on any component yourself, by calling the
raise_event() method. (Any extra keyword parameters to
raise_event() get passed to the event handler function.)
Each component has a fixed set of events it supports (the ones you see in the designer). If you call
raise_event() with an event name that isn’t on that list, it will fail.
The exception are custom events, which are events that begin with
"x-". So you can safely call
raise_event('x-foo') on any component. (Or you can create a custom component, which lets you set the list of supported events yourself.)
(This is to make sure that any custom events you use don’t collide with events that get added to Anvil in future.)
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.
Some components can contain other components. We call these containers, and they all inherit from the
Container class. (All forms are also containers.)
You can add any component to a container in Python by calling the container’s
To add a component to a container in code, call the container’s
add_component() method, and pass the component as its argument.
You can call a container’s
get_components() method to get a list of all the components that have been added to it.
Parents and children
You can look up a component’s container with the
.parent attribute. If a component has not yet been added to a container, its
.parent attribute is
print(btn.parent) # prints "<anvil.XYPanel object>"
You can get a list of all components within a container by calling its
To remove a component from a container, call the component’s
To remove all components from a container, call the container’s
Raising an event on all children
To raise an event on all components in a container, call
<code>container.raise_event_on_children(event_name, <i>extra_args...</i>)</code>. This takes exactly the same parameters as component.raise_event`, and is subject to the same constraints on event names.
For example, it is especially useful when you want to signal to all children of a RepeatingPanel without already having explicit references to those children.
Container Properties are properties that control the relationship between a component and the container it is in; the argument names and their meanings depend on the type of container. They are visible in the Properties panel in the Editor. They can also be passed as keyword arguments to
For example, XYPanels have
width container properties, which determine the position of the component. You can specify them in the designer:
Or you can pass them as keyword arguments when you call
add_component() in your code:
btn = Button(text="Click me") self.xy_panel_1.add_component(btn, x=100, y=100)
For more information on the container properties available for each container type, consult the Anvil API Reference.
A Form can be thought of as a ‘page’ in Anvil. But a Form is not always the entire page. A Form is an Anvil component which can also be used within another Form. This means Anvil apps can be built in a modular way by putting Forms together.
The editor shows a list of Forms in the app browser. You can click on each Form to see it in the Design view, move components around on it and drop components into it.
In Anvil, a Form combines code (a Python module) and a user interface (specified with a visual designer).
In the Design view, you use drag-and-drop to build a template, defining which components should be created for each instance of your form.
In the Code view, a Form is represented by a Python module. This module must define a class of the same name as the form (eg the
MyForm form must define a class called
MyForm), which inherits from the designer template. Its attributes and methods define how the app behaves.
You can write Python code that runs when you click a button, edit a text box, or interact with your app in any other way.
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.
HtmlTemplate is not available for placement in the visual designer. To add one to your app, you can either create a “Custom HTML” form or create an
HtmlTemplate from code.)
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.
All forms also have a property called
item. Its default value is an empty dictionary, and it triggers a data binding refresh whenever it is set.
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.