HTMX Examples

Running some HTMX examples with Bridget.
import fastcore.all as FC
from bridget.common import *

from bridget.helpers import _n
from fasthtml.xtend import Script, Style

# needed for vfile:
app, brt, rt = get_app(show_logger=True, summary=True, cfg={'auto_show':True})
Loaded scripts
loader
htmx
fasthtmljs
observer
brd_mark

Example from css-scope-inline

from fasthtml.components import Button, Span, Div, H2

class Buttons:
    def __ft__(self):
        return (
            Button(garlic=True, hx_get='test', hx_select='button[vampire]', hx_swap='afterend')(_n,
                Style(self._css_.format('hsl(264 80% 47%)', 'hsl(264 80% 60%)')),
                'garlic ', Span('🧄', cls='icon'),
            _n), _n,
            Button(vampire=True, hx_get='test', hx_select='button[garlic]', hx_swap='afterend')(_n,
                Style(self._css_.format('hsl(150 80% 47%)', 'hsl(150 80% 60%)')), 
                'vampire ', Span('🧛', cls='icon'),
            _n), _n,
        )
    _css_ = '''
    me {{ margin: 4px; padding: 10px 30px; min-width: 80px; background: {0}; border-bottom: 0.5rem solid hsl(264 80% 20%); }}
    me {{ color: antiquewhite; font-size: 14pt; font-variant: all-small-caps; font-weight: bold; }}
    me:hover {{ background: {1}; }}
    me span.icon {{ font-size:16pt; }}
'''

@rt("/test")
def get(): return Buttons()
Div()(
    H2('HTMX Test'),
    Div('Buffy: eat garlic! Angel: more mes!'),
    Buttons(),
)

HTMX Test

Buffy: eat garlic! Angel: more mes!

Delete Row

from fasthtml.components import Table, Thead, Tbody, Tr, Th, Td


contacts = [
    {'name': "Joe Smith",       'email': "joe@smith.org",       'status': "Active"},
    {'name': "Angie MacDowell", 'email': "angie@macdowell.org", 'status': "Active"},
    {'name': "Fuqua Tarkenton", 'email': "fuqua@tarkenton.org", 'status': "Active"},
    {'name': "Kim Yee",         'email': "kim@yee.org",         'status': "Inactive"},
]


def row(contact, i):
    return Tr()(
        Td(contact["name"]), Td(contact["email"]), Td(contact["status"]),
        Td()(Button(cls="btn danger", hx_delete=f"/contact/{i}")('Delete'))
    )


tbl = Table(cls="table delete-row-example")(
    Style('''
me tr.htmx-swapping td {
    opacity: 0;
    transition: opacity 1s ease-out;
}
'''),
    Thead()(Tr()(Th('Name'), Th('Email'), Th('Status'), Th())),
    # Tbody(hx_confirm="Are you sure?", hx_target="closest tr", hx_swap="outerHTML swap:1s")(
    Tbody(hx_target="closest tr", hx_swap="outerHTML swap:1s")(
        *(row(contact, i) for i, contact in enumerate(contacts))
    )
)

@rt('/demo')
def get(): return tbl

@rt('/contact/{i}')
def delete(i:int): return ''

tbl
NameEmailStatus
Joe Smithjoe@smith.orgActive
Angie MacDowellangie@macdowell.orgActive
Fuqua Tarkentonfuqua@tarkenton.orgActive
Kim Yeekim@yee.orgInactive
brt('/demo');
Name Email Status
Joe Smith joe@smith.org Active
Angie MacDowell angie@macdowell.org Active
Fuqua Tarkenton fuqua@tarkenton.org Active
Kim Yee kim@yee.org Inactive
<DisplayHandle display_id=6f13b7206dcded6793be1da5cc9700de>

Edit Row

debugger

var _$alert = (btn) => {
    debugger;
    let editing = document.querySelector('.editing')
    if (editing) {
        if (window.confirm('Hey! You are already editing a row! Do you want to cancel that edit and continue?')) {
            htmx.trigger(editing, 'cancel');
            htmx.trigger(btn, 'edit');
        }
    } else {
        htmx.trigger(btn, 'edit')
    }
}
# alertscr = Script('vfile:alertscr', type="module")

Script('vfile:alertscr')
from fasthtml.components import Input

contacts = [
    {'id': 0, 'name': "Joe Smith",       'email': "joe@smith.org",       'status': "Active"},
    {'id': 1, 'name': "Angie MacDowell", 'email': "angie@macdowell.org", 'status': "Active"},
    {'id': 2, 'name': "Fuqua Tarkenton", 'email': "fuqua@tarkenton.org", 'status': "Active"},
    {'id': 3, 'name': "Kim Yee",         'email': "kim@yee.org",         'status': "Inactive"},
]


def editrow(contact):
    return Tr(hx_trigger='cancel', cls='editing', hx_get=f"/eg2/contact/{contact['id']}")(
        Td(Input(name='name', value=contact['name'])),
        Td(Input(name='email', value=contact['email'])),
        Td()(Button(cls="btn danger", hx_get=f"/eg2/contact/{contact['id']}")('Cancel'),
            Button(cls="btn danger", hx_put=f"/eg2/contact/{contact['id']}", hx_include='closest tr')('Save'))
    )

def row(contact):
    return Tr()(
        Td(contact["name"]), Td(contact["email"]),
        Td()(Button('Edit', cls="btn danger", 
            hx_get=f"/eg2/contact/{contact['id']}/edit", hx_trigger="edit", 
            onClick="_$alert(this)")
        )
    )

tbl = Div()(
    Table(cls="table edit-row-example")(
        Thead()(Tr()(Th('Name'), Th('Email'), Th())),
        # Tbody(hx_confirm="Are you sure?", hx_target="closest tr", hx_swap="outerHTML swap:1s")(
        Tbody(hx_target="closest tr", hx_swap="outerHTML")(
            *(row(contact) for contact in contacts)
        )
    ),
    # alertscr
)


@rt('/eg2/contact/{i}{edit:path}')
def get(i:int, edit:str=''):
    # import debugpy; debugpy.debug_this_thread() # vscode needs this to honor breakpoints
    contact = contacts[i]
    if edit: return editrow(contact)
    else: return row(contact)


@rt('/eg2/contact/{i}')
def put(i:int, name:str, email:str):
    # import debugpy; debugpy.debug_this_thread() # vscode needs this to honor breakpoints
    contact = contacts[i]
    contact['name'] = name
    contact['email'] = email
    return row(contact)


tbl
Name Email
Joe Smith joe@smith.org
Angie MacDowell angie@macdowell.org
Fuqua Tarkenton fuqua@tarkenton.org
Kim Yee kim@yee.org