diff --git a/examples/dynamic_user_interface_(htmx)/delete_row/app.py b/examples/dynamic_user_interface_(htmx)/delete_row/app.py new file mode 100644 index 0000000..ccd5298 --- /dev/null +++ b/examples/dynamic_user_interface_(htmx)/delete_row/app.py @@ -0,0 +1,53 @@ +from fasthtml.common import * + +app, rt = fast_app() + +# This represents the data we are rendering +# The data could original from a database, or any other datastore +@dataclass +class Contact: + # Data points + id: int + name: str + email: str + status: str + + def __ft__(self): + # __ft__ method is used by FastHTML to render an item in the UI + # By defining this, a `Contact` will show up as a table row automatically + return Tr( + *map(Td, (self.name, self.email, self.status)), + Td(Button('Delete', + hx_delete=delete.to(id=self.id).lstrip('/'), + # Give a confirmation prompt before deleting + hx_confirm="Are you sure?", + # Target the closest row (The one you clicked on) + hx_target="closest tr", + # Swap out the row with nothing (removes the row) + hx_swap="outerHTML"))) + +# Sample data +# Often this would come from a database +contacts = [{'id':1, 'name': "Bob Deer", 'email': "bob@deer.org", 'status': "Active" }, + {'id':2, 'name': "Jon Doe", 'email': "Jon@doe.com", 'status': "Inactive"}, + {'id':3, 'name': "Jane Smith",'email': "jane@smith.com",'status': "Active" }] + +@rt +def index(sess): + # Save a copy of contacts in your session + # This is the demo doesn't conflict with other users + sess['contacts'] = contacts + # Create initial table + return Table( + Thead(Tr(*map(Th, ["Name", "Email", "Status", ""]))), + # A `Contact` object is rendered as a row automatically using the `__ft__` method + Tbody(*(Contact(**x) for x in sess['contacts']))) + + +@app.delete +def delete(id: int, sess): + sess['contacts'] = [c for c in sess['contacts'] if c['id'] != id] + # Return nothing to the HTMX request to swap in nothing (removes the row) + + +serve() diff --git a/examples/dynamic_user_interface_(htmx)/delete_row/card_thumbnail.gif b/examples/dynamic_user_interface_(htmx)/delete_row/card_thumbnail.gif new file mode 100644 index 0000000..6d356ba Binary files /dev/null and b/examples/dynamic_user_interface_(htmx)/delete_row/card_thumbnail.gif differ diff --git a/examples/dynamic_user_interface_(htmx)/delete_row/card_thumbnail.png b/examples/dynamic_user_interface_(htmx)/delete_row/card_thumbnail.png new file mode 100644 index 0000000..c57407d Binary files /dev/null and b/examples/dynamic_user_interface_(htmx)/delete_row/card_thumbnail.png differ diff --git a/examples/dynamic_user_interface_(htmx)/delete_row/metadata.ini b/examples/dynamic_user_interface_(htmx)/delete_row/metadata.ini new file mode 100644 index 0000000..1e42df8 --- /dev/null +++ b/examples/dynamic_user_interface_(htmx)/delete_row/metadata.ini @@ -0,0 +1,6 @@ +[REQUIRED] +ImageAltText=Delete row +ComponentName=Delete Row +ComponentDescription=Delete a row from table via HTMX + + diff --git a/main.py b/main.py index 16887f1..7491670 100644 --- a/main.py +++ b/main.py @@ -122,8 +122,8 @@ def ImageCard(dir_path): loading="lazy", cls="card-img-top"), href=f"/split/{dpath}"), - Div(P(meta['ComponentName'], cls=(TextT.bold, TextT.large)), - render_md(P(meta['ComponentDescription'])),#, cls=(TextT.muted, TextT.large)), + Div(P(meta['ComponentName'], cls=(TextT.bold, TextT.lg)), + render_md(P(meta['ComponentDescription'])),#, cls=(TextT.muted, TextT.lg)), style="height: 150px; overflow: auto;"), footer=DivFullySpaced( A(Button("Split", cls=ButtonT.primary), href=f"/split/{dpath}"),