HTML Forms
All HTML Forms have an underlying HTML Template. HTML Forms are able to call JavaScript functions defined within the HTML Template.
This reference describes how to interact with those JavaScript functions defined in the HTML Template.
Calling JavaScript
Every HTML Form (that is, any Form except a Blank Panel Form) has a call_js
method that will invoke a JavaScript function.
call_js
method - make sure you’re using a Custom HTML Form.Here is a simple JavaScript function that can be placed in an HTML template of a Custom HTML form.
<script>
function showJsAlert(message) {
alert(message);
return 42;
}
</script>
Here is the code to call that function from Python.
def button_1_click(self, **event_args):
# This method is called when the button gets clicked
self.call_js('showJsAlert', 'Hello, world!')
You can pass any argument to this function. JSON-compatible values (strings, numbers, lists, bools, dicts and None
) are mapped to JavaScript equivalent JSON-compatible values. Non-JSON-compatible values are wrapped. The reverse is also true when calling a Python function from JavaScript. (Note JavaScript dictionary-like objects are returned as dictionaries, unlike return values from the anvil.js
module)
alert() function
instead!You may also use the anvil.js.call()
function to call global JavaScript functions. This does not need to be called from an HTML form, it will work anywhere in client code. The main difference between the self.call_js
method described above, and anvil.js.call()
is the JavaScript this
. See the next section for details.
Referring to the form from JavaScript
When you call a JavaScript function from an HTML Form using self.call_js
, this
is bound to the (jQuery-wrapped) DOM node that represents the form itself (self
). Whereas this
will not be bound when using the anvil.js.call()
function.
Using self.call_js
means you have all the usual jQuery methods available to you, starting from the current component:
// (in JavaScript:)
function setColor(color) {
// Find all the 'div' elements inside this component
var divs = this.find("div");
divs.css("background-color", color)
}
# (in Python)
def button_1_click(self, **event_args):
# This method is called when the button gets clicked
self.call_js('setColor', 'red')
background
property of a component instead!Running JavaScript on Form startup
If you want to run JavaScript on Form startup, run it from the show
event handler.
def form_show(self, **event_args):
"""This method is called when the HTML panel is shown on the screen"""
self.call_js('initMyJavaScriptLibrary')
This executes after the Form has been added to the page. Do not self.call_js()
from your form’s __init__
method.
A Form’s __init__
method runs before the Form is added to the page, and JavaScript in the Form’s HTML template is not executed until it is added to the page.
Implementation detail
If you have multiple functions in the JavaScript global namespace with the same name you cannot guarantee which function will be called when using self.call_js
. This might happen if you have various HTML Forms with the same underlying HTML Template.
Calling Python from JavaScript
Any method on your Custom HTML Form can be called from JavaScript. Imagine you have this method:
def my_method(self, name):
alert(f"Hello, {name}")
return 42
To call into Python from JavaScript, use anvil.call()
within a JavaScript function.
// (in JavaScript:)
function myFunc() {
anvil.call($('.content'), 'my_method', 'world')
}
The first argument is a DOM element (optionally jQuery-wrapped) that indicates which Form instance you would like to call the function on. It is not necessary to specify the exact DOM element of the Form; any child element will work. It is an error to pass a first argument that is not an Anvil HTML Form or a child of an HTML Form.
The second argument is a method name, and all other arguments are passed to the Python method.
anvil.call
is the name of a Python method on a Custom HTML Form. Make sure you’re using a Custom HTML Form, not a Blank Panel Form.Asynchronous JavaScript
anvil.call()
returns a Promise, which resolves to the method’s return value (if it returns), or rejects with an exception object (if it throws an exception). If the method throws an exception, the exception stack trace will be captured in the Anvil logs, regardless of the JavaScript’s behaviour.
An Example of Asynchronous JavaScript
# (in Python)
def my_method(self, name):
alert(f"Hello, {name}")
return 42
// (in JavaScript:)
// Pop up a "Hello, World" Anvil alert when my-link
// is clicked.
$('.my-link').on('click', function(e) {
var linkElement = this;
anvil.call(linkElement, "my_method", "World")
.then(function (r) {
// resolves after the python function has exectuted
// in this case r will be 42
console.log("The function returned:", r);
});
e.preventDefault();
});
If you call a JavaScript function from an Anvil form, and it returns a Promise, Python execution will block until that promise resolves (in which case, the resolved value is returned) or rejects (in which case, the rejected value is thrown with an ExternalError
exception).
// (in JavaScript:)
function sleepForSomeTime(duration) {
return new Promise(function(resolve, reject) {
setTimeout(function() { resolve(42); }, duration)
})
}
Here’s the Python code that runs that JavaScript:
# When the button is clicked, it will wait 5 seconds
# before printing '42' to the Output Panel:
def button_1_click(self, **event_args):
r = self.call_js('sleepForSomeTime', 5000)
print(r)
Do you still have questions?
Our Community Forum is full of helpful information and Anvil experts.