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.

Accessing Javascript

Interaction with Javascript objects in Anvil is primarily done through the anvil.js module. This reference provides some details about working with Javascript objects from Python code.

Check out the Quickstart guide for an introduction applied to an external library.

HTML Forms also have a unique way to interact with their HTML Template Javascript functions described here.

Accessing the window

You can access any Javascript function or variable by importing it from the window object. The window object can be thought of as the Javascript global namespace in the browser where your app runs.

from anvil.js.window import Foo
# Foo is a Javascript object defined in the Javascript namespace

Accessing a DOM Node

You can access the DOM node for any Anvil Component in Python

anvil.js.get_dom_node(component)
# access any anvil component's DOM node

Return values from anvil.js

When using anvil.js, Javascript objects will be returned as Python objects. Javascript strings, numbers, arrays, booleans, null, and undefined are mapped to their Python equivalents.

All other Javascript objects (including dictionary-like objects) will be returned as proxyobjects. Proxyobjects are Python objects that wrap a Javascript object and allow you to interact with the underlying Javascript object from Python code.

from anvil.js.window import Foo
print(type(Foo)) # <class 'Proxy'>

Return values from anvil.js.get_dom_node are also proxyobjects.

dom_node = anvil.js.get_dom_node(self.content_panel)
print(dom_node) # <HTMLDivElement proxyobject>

As is the window object!

print(anvil.js.window) # <Window proxyobject>

Working with proxyobjects

Attributes

You can access the attributes on the underlying Javascript object in Python as you would in Javascript.

Foo.bar     # use . notation
Foo['bar']  # use [] subscript notation

Javascript attributes will be returned to Python in the same way as described above i.e. Javascript strings, numbers, arrays, booleans, null, and undefined will be returned as their Python equivalents. All other Javascript objects will be returned as proxyobjects.

Calling dir() on a proxyobject, e.g. dir(Foo), will give an indication of the available attributes accessible in Python. Only Javascript enumerable properties of the underlying Javascript object will be returned when calling dir().

If you are using Javascript objects from an external library, it is always a good idea to check the documentation.

All proxyobjects have a keys() method e.g. Foo.keys(). Calling keys() returns a list of strings, which represents the underlying Javascript object’s own property names. It is the equivalent in Javascript of doing Object.keys(js_object)

All proxyobjects have a get() method e.g. Foo.get('bar', None). The default value will be returned if the attribute is not found. If no default value is provided then None will be used as the default value.

Iteration

If an object is iterable in Javascript then it will be iterable in Python.
A Javascript object is only iterable if it has a Symbol.iterator symbol.

from anvil.js.window import jQuery

for element in jQuery('div'):
    # jQuery objects are iterable in Javascript
    # and therefore iterable in Python
    print(element)

Typically proxyobjects are not iterable - but you can iterate over the keys.

for key in proxy_obj.keys():
    val = proxy_obj[key]

__class__

Accessing .__class__ of a proxyobject will return the constructor of the underlying Javascript object.

x = Foo()
print(x)           # <Foo proxyobject>
print(x.__class__) # <proxyclass 'Foo'> (the Javascript constructor)
print(type(x))     # <class 'Proxy'>

True or False

All proxyobjects are considered ‘Truthy’ (i.e. bool(proxy_obj) will be True) unless:

  • the underlying Javascript object is empty: {}
  • the proxyobject can be called with len and len(proxy_obj) == 0

len()

You can call len() on a proxyobject if the underlying Javascript object is not a function and has a .length property.

from anvil.js.window import jQuery

print(len(jQuery('div')))
# jQuery objects have .length property and can be called with len()

Calling proxyobjects

If the underlying Javascript object is callable, then the proxyobject is callable in Python.
Kwargs will not work when calling proxyobjects since kwargs are not supported in Javascript.

When calling a proxyobject:

  • the arguments will be converted to Javascript,
  • the underlying Javascript function will be called with those arguments
  • the return value will be converted to Python.

If you send a Python function to a proxyobject as a callable, the reverse is true. See the Quickstart guide for an example.

*Implementation Detail: If a proxyobject is called and the underlying Javascript function returns a Promise, then the Python execution will pause until the Promise resolves before continuing the execution. See additional notes on asynchronous Javascript.*

You can know if a proxyobject is callable by calling print() on the proxyobject or by using callable().

from anvil.js.window import Foo

print(Foo)
#   <proxyclass 'Foo'>, or
#   <proxyfunction 'Foo'>, or
#   <bound proxymethod 'Foo' of <Window proxyobject>>
print(callable(Foo)) 
# True

Calling with new

Some libraries will include constructors that require the use of the new operator.

When calling a proxyobject, Python will infer whether new should be used based on the context and the underlying Javascript object being called.

If you want to control when the new operator is used, you can use anvil.js.new or anvil.js.call.

from anvil.js.window import Foo
import anvil.js

anvil.js.new(Foo, 1, 'a')  # Foo will be called with the new keyword
anvil.js.call(Foo, 1, 'a') # Foo will be called without the new keyword
anvil.js.call('Foo')
anvil.js.call(anvil.js.window['Foo'])
anvil.js.window.Foo()
Are three ways of calling a Javascript function from Python

Converting to Python

A proxyobject, which is a dictionary-like, is easily converted into a Python dictionary.

print(proxy_obj) # proxyobject({'a': 1, 'b': 2})
dict(proxy_obj)  # {'a': 1, 'b': 2}
{**proxy_obj}    # {'a': 1, 'b': 2} 

The above code works for all proxyobjects regardless of the underlying Javascript object. However, only the keys returned from the .keys() method will be included in the dictionary object. Thus it is unlikely to be suitable for most proxyobjects.

You can determine if the proxyobject is dictionary-like by inspecting it with print().

print(proxy_obj) # proxyobject({'a': 1, 'b': 2}) (dictionary-like)
print(Foo())     # <Foo proxyobject>      (not dictionary-like)

More specifically, a proxyobject is considered dictionary-like when the underlying Javascript object is an object literal.

Proxyobjects cannot be sent to the server and must be converted to a dictionary or mapped to another portable type.