File size: 2,497 Bytes
2531445
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0760113
2531445
 
0760113
2531445
 
 
 
 
 
 
3b5501b
0760113
2531445
 
0760113
2531445
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
from fasthtml.common import H3, Button, Div, Form, Hr, Input, Progress, Script, fast_app
from starlette.datastructures import UploadFile

app, rt = fast_app(hdrs=[Script(src="https://unpkg.com/[email protected]")])


@app.get
def page():
    return Div(
        Div(H3("Method 1: Pure JS"), Div(method1())),
        Hr(),
        Div(H3("Method 2: Hyperscript"), Div(method2())),
        cls="container",
    )


@app.get
def method1():
    js = """
    htmx.on('#form', 'htmx:xhr:progress', function(evt) {
        htmx.find('#progress').setAttribute('value', evt.detail.loaded/evt.detail.total * 100)
    });
    """
    form = Form(hx_target="#output", hx_post=upload, id="form")(
        Input(type="file", name="file"),
        Button("Upload"),
        Progress(id="progress", value="0", max="100", style="margin-top:20px"),
        Div(id="output"),
    )
    return form, Script(js)


@app.get
def method2():
    script = "on htmx:xhr:progress(loaded, total) set #progress2.value to (loaded/total)*100"
    return Form(_=script, hx_target="#output2", hx_post=upload)(
        Input(type="file", name="file"),
        Button("Upload"),
        Progress(id="progress2", value="0", max="100", style="margin-top:20px"),
        Div(id="output2"),
    )


@app.post
async def upload(file: UploadFile):
    # print(len(await file.read()))
    return Div(f"Uploaded! Filename: {file.filename}. Filesize: {file.size}")


DESC = "Demonstrates how to upload a file via ajax with a progress bar"
DOC = """
In this example we show how to create a file upload form that will be submitted via ajax, along with a progress bar.

We will show two different implementation, one in pure javascript (using some utility methods in htmx) and one in hyperscript

First the pure javascript version.

 - We have a form of type multipart/form-data so that the file will be properly encoded
 - We post the form to /upload
 - We have a progress element
 - We listen for the htmx:xhr:progress event and update the value attribute of the progress bar based on the loaded and total properties in the event detail.

::method1::

The Hyperscript version is very similar, except:

The script is embedded directly on the form element
Hyperscript offers nicer syntax (although the htmx API is pretty nice too!)
```python
app, rt = fast_app(hdrs=[Script(src="https://unpkg.com/[email protected]")])
```
::method2::

Note that hyperscript allows you to destructure properties from details directly into variables
"""