Sharing an Example of Using PyScript and HTMX on a note type

I wanted to share a fun experiment I put together (with the help of AI, of course). I’ve wanted to try out PyScript for a while now, and I finally got around to testing it out in the context of an Anki note type. This example shows how you can add dynamic content to an Anki card using:

  • PyScript on it’s own
  • HTMX + PyScript
  • Tailwind for styling
{{Front}}

<link rel="stylesheet" href="https://pyscript.net/releases/2024.10.1/core.css">
<script type="module" src="https://pyscript.net/releases/2024.10.1/core.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/htmx.org@1.9.2"></script>

<script type="py">
from pyscript import document
from pyscript.ffi import create_proxy
import js, json

# Fetch multiple cat facts in Python
async def fetch_multiple_facts(event):
    # read & clamp user input
    val = document.getElementById("limitInput").value
    try:
        n = int(val)
    except:
        n = 1
    n = max(1, min(n, 10))
    # fetch list of facts
    res = await js.fetch(f"https://catfact.ninja/facts?limit={n}")
    js_data = await res.json()
    py_data = js_data.to_py()
    # build HTML list
    items = "".join(f"<li class='mb-2'>{f['fact']}</li>" for f in py_data["data"])
    document.getElementById("pyFactsList").innerHTML = \
        f"<ul class='list-disc list-inside'>{items}</ul>"

# htmx:afterSwap handler in Python
def on_htmx_swap(evt):
    detail = evt.detail
    if detail.target.id == "htmxFactsList":
        try:
            data = json.loads(detail.xhr.responseText)
            items = "".join(f"<li class='mb-2'>{f['fact']}</li>" for f in data["data"])
            detail.target.innerHTML = f"<ul class='list-disc list-inside'>{items}</ul>"
        except Exception as e:
            detail.target.innerText = "Error rendering facts"
            print("htmx swap render error:", e)

# bind Python event‐handlers
btn_py   = document.getElementById("pyBtn")
btn_py.addEventListener("click", create_proxy(fetch_multiple_facts))

# listen for all htmx swaps
js.document.addEventListener("htmx:afterSwap", create_proxy(on_htmx_swap))
</script>

<!-- === Input for number of facts === -->
<div class="p-4 bg-white rounded-lg shadow mb-4">
  <label for="limitInput" class="block mb-1 font-semibold">Number of facts (1 – 10):</label>
  <input
    id="limitInput"
    name="limit"
    type="number"
    min="1"
    max="10"
    value="3"
    class="border border-gray-300 rounded px-3 py-2 w-20 focus:ring-2 focus:ring-blue-300"
  />
</div>

<!-- === Pure PyScript Example === -->
<div class="p-4 bg-gray-50 rounded-lg shadow mb-4">
  <button
    id="pyBtn"
    class="px-4 py-2 bg-indigo-500 hover:bg-indigo-700 text-white font-bold rounded mb-2"
  >
    Get Cat Facts (PyScript)
  </button>
  <div id="pyFactsList" class="mt-3 text-gray-800">
    Enter a number and click above…
  </div>
</div>

<!-- === htmx + PyScript Example === -->
<div class="p-4 bg-pink-50 rounded-lg shadow">
  <button
    hx-get="https://catfact.ninja/facts"
    hx-include="#limitInput"
    hx-headers='{"Accept":"application/json"}'
    hx-trigger="click"
    hx-target="#htmxFactsList"
    hx-swap="innerHTML"
    class="px-4 py-2 bg-pink-500 hover:bg-pink-700 text-white font-bold rounded mb-2"
  >
    Get Cat Facts (htmx)
  </button>
  <div id="htmxFactsList" class="mt-3 text-gray-800">
    Enter a number and click above…
  </div>
</div>

Thought I’d share to see if anybody has other ideas about fun things to do with HTMX and/or PyScript. :nerd_face:

3 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.