Reputation:
I would like to run an Python script on Browser when clicking a button (on a html file). Something close to this:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
<py-env>
</py-env>
</head>
<body>
<button type="button" onclick="runPython()">run Python</button>
<script>
function runPython() {
<py-script>
print("you clicked me")
</py-script>
}
</script>
</body>
</html>
Upvotes: 3
Views: 14808
Reputation: 461
You can do it without the javascript's <script>
and function
. You already have pyscript. Change the onClick
property of the button to pys-onClick
and add an id property to the button, which you will then use in the python function pyscript.write('element-id', 'element-value', append=False)
:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
<py-env>
</py-env>
</head>
<body>
<button id="thebuttonid" type="button" pys-onClick="runPython">run Python</button>
<py-script>
def runPython(*args):
pyscript.write("thebuttonid", "you clicked me")
</py-script>
</body>
</html>
This only works if the button with the pys-onClick
has an id. The id provided to the pyscript.write
function is the id of the element you want to write into. In this particular case it happened to be the same element you're calling the function from. The function needs to receive arguments (hence *args
) because it is receiving a pyodide javascript proxy as argument. A full annotated version would be:
<py-script>
from pyodide import JsProxy
def runPython(proxy: JsProxy) -> None:
"""
Writes 'you clicked me' in the html element with the id 'thebuttonid'.
This function must be called from an element with the property pys-onClick='runPython'.
"""
pyscript.write("thebuttonid", "you clicked me")
</py-script>
Now since you're using pyscript you can replace the regular html button with a py-button:
<py-button id="thebuttonid" label="run Python" type="button" pys-onClick="runPython"></py-button>
It'll get styled by tailwind css because you imported the css file at the header. Notice that you have to move the label to a property instead of using it as the value of the button.
Upvotes: 3
Reputation: 141
<html>
<head>
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<link rel = 'stylesheet' href = "https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>
<body>
<button id = "show_output" class = "btn btn-primary" type = "submit" pys-onClick="show_output">Show Output</button>
<div id="output_div" style="margin-top: 10px;margin-bottom: 10px;"></div>
<py-script>
def show_output(*args, **kwargs):
output = Element("output_div")
output.write("You Clicked Me!")
</py-script>
</body>
</html>
Upvotes: 4
Reputation: 81336
To call Python code from JavaScript requires creating a proxy. This proxy handles type (data) translation to and from JavaScript.
To create a proxy:
from js import document
from pyodide import create_proxy
function_proxy = create_proxy(runPython)
Change your HTML element declaration to declare an ID and remove the onClick:
<button type="button" id="button">run Python</button>
Assign the proxy to an event listener for the button:
e = document.getElementById("button")
e.addEventListener("click", function_proxy)
This style is very similar to how JavaScript also assigns event listeners.
Put this together:
<body>
<button type="button" id="button">run Python</button>
<py-script>
from js import document
from pyodide import create_proxy
def runPython():
print("you clicked me")
function_proxy = create_proxy(runPython)
document.getElementById("button").addEventListener("click", function_proxy)
</py-script>
</body>
I wrote several articles on JavaScript and Python:
Upvotes: 11