mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-19 18:27:29 -05:00
Add docs for py-event* (#1300)
* Fix markdown Add event-handlers.md * Address changes from Jeff + Antonion and add it to index * how tos don't exist anymore theyre now guides * Restore p on contributing * Adding changelog * Aadd space * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Carmelo <carmelofiorello@gmail.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -4,14 +4,21 @@ Thank you for wanting to contribute to the PyScript project!
|
|||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
|
||||||
|
- [Contributing to PyScript](#contributing-to-pyscript)
|
||||||
|
- [Table of contents](#table-of-contents)
|
||||||
- [Code of Conduct](#code-of-conduct)
|
- [Code of Conduct](#code-of-conduct)
|
||||||
- [Contributing](#contributing)
|
- [Contributing](#contributing)
|
||||||
- [Reporting bugs](#reporting-bugs)
|
- [Reporting bugs](#reporting-bugs)
|
||||||
|
- [Creating useful issues](#creating-useful-issues)
|
||||||
- [Reporting security issues](#reporting-security-issues)
|
- [Reporting security issues](#reporting-security-issues)
|
||||||
- [Asking questions](#asking-questions)
|
- [Asking questions](#asking-questions)
|
||||||
- [Setting up your local environment and developing](#setting-up-your-local-environment-and-developing)
|
- [Setting up your local environment and developing](#setting-up-your-local-environment-and-developing)
|
||||||
|
- [Developing](#developing)
|
||||||
|
- [Rebasing changes](#rebasing-changes)
|
||||||
|
- [Building the docs](#building-the-docs)
|
||||||
- [Places to start](#places-to-start)
|
- [Places to start](#places-to-start)
|
||||||
- [Setting up your local environment and developing](#setting-up-your-local-environment-and-developing)
|
- [Setting up your local environment and developing](#setting-up-your-local-environment-and-developing)
|
||||||
|
- [Submitting a change](#submitting-a-change)
|
||||||
- [License terms for contributions](#license-terms-for-contributions)
|
- [License terms for contributions](#license-terms-for-contributions)
|
||||||
- [Becoming a maintainer](#becoming-a-maintainer)
|
- [Becoming a maintainer](#becoming-a-maintainer)
|
||||||
- [Trademarks](#trademarks)
|
- [Trademarks](#trademarks)
|
||||||
@@ -43,7 +50,7 @@ If you have questions about the project, using PyScript, or anything else, pleas
|
|||||||
|
|
||||||
## Places to start
|
## Places to start
|
||||||
|
|
||||||
If you would like to contribute to PyScript, but you aren't sure where to begin, here are some suggestions.
|
If you would like to contribute to PyScript, but you aren't sure where to begin, here are some suggestions:
|
||||||
|
|
||||||
- **Read over the existing documentation.** Are there things missing, or could they be clearer? Make some changes/additions to those documents.
|
- **Read over the existing documentation.** Are there things missing, or could they be clearer? Make some changes/additions to those documents.
|
||||||
- **Review the open issues.** Are they clear? Can you reproduce them? You can add comments, clarifications, or additions to those issues. If you think you have an idea of how to address the issue, submit a fix!
|
- **Review the open issues.** Are they clear? Can you reproduce them? You can add comments, clarifications, or additions to those issues. If you think you have an idea of how to address the issue, submit a fix!
|
||||||
|
|||||||
@@ -35,7 +35,12 @@ Enhancements
|
|||||||
- migrated from *rollup* to *esbuild* to create artifacts
|
- migrated from *rollup* to *esbuild* to create artifacts
|
||||||
- updated `@codemirror` dependency to its latest
|
- updated `@codemirror` dependency to its latest
|
||||||
|
|
||||||
2023.03.1
|
Docs
|
||||||
|
----
|
||||||
|
|
||||||
|
- Add docs for event handlers
|
||||||
|
|
||||||
|
2023.01.1
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
179
docs/guides/event-handlers.md
Normal file
179
docs/guides/event-handlers.md
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
# Event handlers in PyScript
|
||||||
|
|
||||||
|
PyScript offer two ways to subscribe to Javascript event handlers:
|
||||||
|
|
||||||
|
## Subscribe to event with `py-*` attributes
|
||||||
|
|
||||||
|
The value of the attribute contains python code which will be executed when the event is fired. A very common pattern is to call a function which does further work, for example:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<button id="noParam" py-click="say_hello_no_param()">
|
||||||
|
No Event - No Params py-click
|
||||||
|
</button>
|
||||||
|
<button id="withParam" py-click="say_hello_with_param('World')">
|
||||||
|
No Event - With Params py-click
|
||||||
|
</button>
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
<py-script>
|
||||||
|
def say_hello_no_param():
|
||||||
|
print("Hello!")
|
||||||
|
|
||||||
|
def say_hello_with_param(name):
|
||||||
|
print("Hello " + name + "!")
|
||||||
|
</py-script>
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that py-\* attributes need a _function call_
|
||||||
|
|
||||||
|
Supported py-\* attributes can be seen in the [PyScript API reference](<[../api-reference.md](https://github.com/pyscript/pyscript/blob/66b57bf812dcc472ed6ffee075ace5ced89bbc7c/pyscriptjs/src/components/pyscript.ts#L119-L260)>).
|
||||||
|
|
||||||
|
## Subscribe to event with `addEventListener`
|
||||||
|
|
||||||
|
You can also subscribe to an event using the `addEventListener` method of the DOM element. This is useful if you want to pass event object to the event handler.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<button id="two">add_event_listener passes event</button>
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
<py-script>
|
||||||
|
from js import console, document
|
||||||
|
from pyodide.ffi.wrappers import add_event_listener
|
||||||
|
|
||||||
|
def hello_args(*args):
|
||||||
|
console.log(f"Hi! I got some args! {args}")
|
||||||
|
|
||||||
|
add_event_listener(document.getElementById("two"), "click", hello_args)
|
||||||
|
</py-script>
|
||||||
|
```
|
||||||
|
|
||||||
|
or using the `addEventListener` method of the DOM element:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<button id="three">add_event_listener passes event</button>
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
<py-script>
|
||||||
|
from js import console, document
|
||||||
|
from pyodide.ffi import create_proxy
|
||||||
|
|
||||||
|
def hello_args(*args):
|
||||||
|
console.log(f"Hi! I got some args! {args}")
|
||||||
|
|
||||||
|
document.getElementById("three").addEventListener("click", create_proxy(hello_args))
|
||||||
|
</py-script>
|
||||||
|
```
|
||||||
|
|
||||||
|
or using the PyScript Element class:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<button id="four">add_event_listener passes event</button>
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
<py-script>
|
||||||
|
from js import console
|
||||||
|
from pyodide.ffi import create_proxy
|
||||||
|
|
||||||
|
def hello_args(*args):
|
||||||
|
console.log(f"Hi! I got some args! {args}")
|
||||||
|
|
||||||
|
Element("four").element.addEventListener("click", create_proxy(hello_args))
|
||||||
|
</py-script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## JavaScript to PyScript and From PyScript to JavaScript
|
||||||
|
|
||||||
|
If you're wondering about how to pass objects from JavaScript to PyScript and/or the other way around head over to the [Passing Objects](passing-objects.md) page.
|
||||||
|
|
||||||
|
|
||||||
|
### Exporting all Global Python Objects
|
||||||
|
|
||||||
|
We can use our new `createObject` function to "export" the entire Python global object dictionary as a JavaScript object:
|
||||||
|
|
||||||
|
```python
|
||||||
|
<py-script>
|
||||||
|
from js import createObject
|
||||||
|
from pyodide.ffi import create_proxy
|
||||||
|
createObject(create_proxy(globals()), "pyodideGlobals")
|
||||||
|
</py-script>
|
||||||
|
```
|
||||||
|
|
||||||
|
This will make all Python global variables available in JavaScript with `pyodideGlobals.get('my_variable_name')`.
|
||||||
|
|
||||||
|
(Since PyScript tags evaluate _after_ all JavaScript on the page, we can't just dump a `console.log(...)` into a `<script>` tag, since that tag will evaluate before any PyScript has a chance to. We need to delay accessing the Python variable in JavaScript until after the Python code has a chance to run. The following example uses a button with `id="do-math"` to achieve this, but any method would be valid.)
|
||||||
|
|
||||||
|
```python
|
||||||
|
<py-script>
|
||||||
|
# create some Python objects:
|
||||||
|
symbols = {'pi': 3.1415926, 'e': 2.7182818}
|
||||||
|
|
||||||
|
def rough_exponential(x):
|
||||||
|
return symbols['e']**x
|
||||||
|
|
||||||
|
class Circle():
|
||||||
|
def __init__(self, radius):
|
||||||
|
self.radius = radius
|
||||||
|
|
||||||
|
@property
|
||||||
|
def area:
|
||||||
|
return symbols['pi'] * self.radius**2
|
||||||
|
</py-script>
|
||||||
|
```
|
||||||
|
|
||||||
|
```html
|
||||||
|
<input type="button" value="Log Python Variables" id="do-mmath" />
|
||||||
|
<script>
|
||||||
|
document.getElementById("do-math").addEventListener("click", () => {
|
||||||
|
const exp = pyodideGlobals.get("rough_exponential");
|
||||||
|
console.log("e squared is about ${exp(2)}");
|
||||||
|
const c = pyodideGlobals.get("Circle")(4);
|
||||||
|
console.log("The area of c is ${c.area}");
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Exporting Individual Python Objects
|
||||||
|
|
||||||
|
We can also export individual Python objects to the JavaScript global scope if we wish.
|
||||||
|
|
||||||
|
(As above, the following example uses a button to delay the execution of the `<script>` until after the PyScript has run.)
|
||||||
|
|
||||||
|
```python
|
||||||
|
<py-script>
|
||||||
|
import js
|
||||||
|
from pyodide.ffi import create_proxy
|
||||||
|
|
||||||
|
# Create 3 python objects
|
||||||
|
language = "Python 3"
|
||||||
|
animals = ['dog', 'cat', 'bird']
|
||||||
|
multiply3 = lambda a, b, c: a * b * c
|
||||||
|
|
||||||
|
# js object can be named the same as Python objects...
|
||||||
|
js.createObject(language, "language")
|
||||||
|
|
||||||
|
# ...but don't have to be
|
||||||
|
js.createObject(create_proxy(animals), "animals_from_py")
|
||||||
|
|
||||||
|
# functions are objects too, in both Python and Javascript
|
||||||
|
js.createObject(create_proxy(multiply3), "multiply")
|
||||||
|
</py-script>
|
||||||
|
```
|
||||||
|
|
||||||
|
```html
|
||||||
|
<input type="button" value="Log Python Variables" id="log-python-variables" />
|
||||||
|
<script>
|
||||||
|
document
|
||||||
|
.getElementById("log-python-variables")
|
||||||
|
.addEventListener("click", () => {
|
||||||
|
console.log(`Nice job using ${language}`);
|
||||||
|
for (const animal of animals_from_py) {
|
||||||
|
console.log(`Do you like ${animal}s? `);
|
||||||
|
}
|
||||||
|
console.log(`2 times 3 times 4 is ${multiply(2, 3, 4)}`);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
```
|
||||||
@@ -35,7 +35,8 @@ for dealing with the response, such as `json()` or `status`. See the
|
|||||||
[FetchResponse documentation](https://pyodide.org/en/stable/usage/api/python-api/http.html#pyodide.http.FetchResponse)
|
[FetchResponse documentation](https://pyodide.org/en/stable/usage/api/python-api/http.html#pyodide.http.FetchResponse)
|
||||||
for more information.
|
for more information.
|
||||||
|
|
||||||
# Example
|
## Example
|
||||||
|
|
||||||
We will make async HTTP requests to [JSONPlaceholder](https://jsonplaceholder.typicode.com/)'s fake API using `pyfetch`.
|
We will make async HTTP requests to [JSONPlaceholder](https://jsonplaceholder.typicode.com/)'s fake API using `pyfetch`.
|
||||||
First we write a helper function in pure Python that makes a request and returns the response. This function
|
First we write a helper function in pure Python that makes a request and returns the response. This function
|
||||||
makes it easier to make specific types of requests with the most common parameters.
|
makes it easier to make specific types of requests with the most common parameters.
|
||||||
@@ -70,6 +71,7 @@ async def request(url: str, method: str = "GET", body: Optional[str] = None,
|
|||||||
response = await pyfetch(url, **kwargs)
|
response = await pyfetch(url, **kwargs)
|
||||||
return response
|
return response
|
||||||
```
|
```
|
||||||
|
|
||||||
This function is a wrapper for `pyfetch`, which is a wrapper for the `fetch` API. It is a coroutine function,
|
This function is a wrapper for `pyfetch`, which is a wrapper for the `fetch` API. It is a coroutine function,
|
||||||
so it must be awaited. It also has type hints, which are not required, but are useful for IDEs and other tools.
|
so it must be awaited. It also has type hints, which are not required, but are useful for IDEs and other tools.
|
||||||
The basic idea is that the `PyScript` will import and call this function, then await the response. Therefore,
|
The basic idea is that the `PyScript` will import and call this function, then await the response. Therefore,
|
||||||
@@ -160,7 +162,8 @@ concluding html code.
|
|||||||
The very first thing to notice is the `py-config` tag. This tag is used to import Python files into the `PyScript`.
|
The very first thing to notice is the `py-config` tag. This tag is used to import Python files into the `PyScript`.
|
||||||
In this case, we are importing the `request.py` file, which contains the `request` function we wrote above.
|
In this case, we are importing the `request.py` file, which contains the `request` function we wrote above.
|
||||||
|
|
||||||
### `py-script` tag for making async HTTP requests.
|
### `py-script` tag for making async HTTP requests
|
||||||
|
|
||||||
Next, the `py-script` tag contains the actual Python code where we import `asyncio` and `json`,
|
Next, the `py-script` tag contains the actual Python code where we import `asyncio` and `json`,
|
||||||
which are required or helpful for the `request` function.
|
which are required or helpful for the `request` function.
|
||||||
The `# GET`, `# POST`, `# PUT`, `# DELETE` blocks show examples of how to use the `request` function to make basic
|
The `# GET`, `# POST`, `# PUT`, `# DELETE` blocks show examples of how to use the `request` function to make basic
|
||||||
@@ -169,6 +172,7 @@ HTTP requests. The `await` keyword is required not only for the `request` functi
|
|||||||
faster ones.
|
faster ones.
|
||||||
|
|
||||||
### HTTP Requests
|
### HTTP Requests
|
||||||
|
|
||||||
HTTP requests are a very common way to communicate with a server. They are used for everything from getting data from
|
HTTP requests are a very common way to communicate with a server. They are used for everything from getting data from
|
||||||
a database, to sending emails, to authorization, and more. Due to safety concerns, files loaded from the
|
a database, to sending emails, to authorization, and more. Due to safety concerns, files loaded from the
|
||||||
local file system are not accessible by `PyScript`. Therefore, the proper way to load data into `PyScript` is also
|
local file system are not accessible by `PyScript`. Therefore, the proper way to load data into `PyScript` is also
|
||||||
@@ -182,31 +186,38 @@ function or to `pyfetch`. See the
|
|||||||
HTTP requests are defined by standards-setting bodies in [RFC 1945](https://www.rfc-editor.org/info/rfc1945) and
|
HTTP requests are defined by standards-setting bodies in [RFC 1945](https://www.rfc-editor.org/info/rfc1945) and
|
||||||
[RFC 9110](https://www.rfc-editor.org/info/rfc9110).
|
[RFC 9110](https://www.rfc-editor.org/info/rfc9110).
|
||||||
|
|
||||||
# Conclusion
|
## Conclusion
|
||||||
|
|
||||||
This tutorial demonstrates how to make HTTP requests using `pyfetch` and the `FetchResponse` objects. Importing Python
|
This tutorial demonstrates how to make HTTP requests using `pyfetch` and the `FetchResponse` objects. Importing Python
|
||||||
code/files into the `PyScript` using the `py-config` tag is also covered.
|
code/files into the `PyScript` using the `py-config` tag is also covered.
|
||||||
|
|
||||||
Although a simple example, the principals here can be used to create complex web applications inside of `PyScript`,
|
Although a simple example, the principals here can be used to create complex web applications inside of `PyScript`,
|
||||||
or load data into `PyScript` for use by an application, all served as a static HTML page, which is pretty amazing!
|
or load data into `PyScript` for use by an application, all served as a static HTML page, which is pretty amazing!
|
||||||
|
|
||||||
|
## API Quick Reference
|
||||||
|
|
||||||
# API Quick Reference
|
|
||||||
## pyodide.http.pyfetch
|
## pyodide.http.pyfetch
|
||||||
### Usage
|
|
||||||
|
### pyfetch Usage
|
||||||
|
|
||||||
```python
|
```python
|
||||||
await pyodide.http.pyfetch(url: str, **kwargs: Any) -> FetchResponse
|
await pyodide.http.pyfetch(url: str, **kwargs: Any) -> FetchResponse
|
||||||
```
|
```
|
||||||
|
|
||||||
Use `pyfetch` to make HTTP requests in `PyScript`. This is a wrapper around the `fetch` API. Returns a `FetchResponse`.
|
Use `pyfetch` to make HTTP requests in `PyScript`. This is a wrapper around the `fetch` API. Returns a `FetchResponse`.
|
||||||
|
|
||||||
- [`pyfetch` Docs.](https://pyodide.org/en/stable/usage/api/python-api/http.html#pyodide.http.pyfetch)
|
- [`pyfetch` Docs.](https://pyodide.org/en/stable/usage/api/python-api/http.html#pyodide.http.pyfetch)
|
||||||
|
|
||||||
## pyodide.http.FetchResponse
|
## pyodide.http.FetchResponse
|
||||||
### Usage
|
|
||||||
|
### FetchResponse Usage
|
||||||
|
|
||||||
```python
|
```python
|
||||||
response: pyodide.http.FetchResponse = await <pyfetch call>
|
response: pyodide.http.FetchResponse = await <pyfetch call>
|
||||||
status = response.status
|
status = response.status
|
||||||
json = await response.json()
|
json = await response.json()
|
||||||
```
|
```
|
||||||
|
|
||||||
Class for handling HTTP responses. This is a wrapper around the `JavaScript` fetch `Response`. Contains common (async)
|
Class for handling HTTP responses. This is a wrapper around the `JavaScript` fetch `Response`. Contains common (async)
|
||||||
methods and properties for handling HTTP responses, such as `json()`, `url`, `status`, `headers`, etc.
|
methods and properties for handling HTTP responses, such as `json()`, `url`, `status`, `headers`, etc.
|
||||||
|
|
||||||
|
|||||||
@@ -18,4 +18,5 @@ passing-objects
|
|||||||
http-requests
|
http-requests
|
||||||
asyncio
|
asyncio
|
||||||
custom-plugins
|
custom-plugins
|
||||||
|
event-handlers
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user