HTMX + Django: Form Submits as GET Instead of POST When Editing Event

Hi all,

I’m integrating HTMX with Django for a calendar/events feature, using a modal for editing and adding events. When I try to edit an event and hit “Save Event” (which should POST the form), the request goes to my event_edit_partial view as a GET instead of a POST.

Key points:

  • The form is rendered into a modal (_event_form.html), with hx-post set to the correct endpoint and method="POST".
  • Creating new events works as expected (POST), but editing an event always triggers a GET on save.
  • The modal is loaded by fetching detail JSON, then HTMX is used for the Edit button in the modal.

Relevant Code:

_event_form.html

<form
  id="event-form"
  method="POST"
  hx-post="{{ form_action }}"
  hx-target="#event-modal-body"
  hx-swap="innerHTML"
>
  {% csrf_token %}
  {{ form.as_p }}

  <div class="d-grid gap-2">
    <button type="submit" class="btn btn-primary">Save Event</button>
    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
  </div>
</form>

_event_detail.html (Edit button triggers HTMX load of edit form)

<button 
  class="btn btn-secondary"
  hx-get="{% url 'event_edit_partial' event.id %}"
  hx-target="#event-modal-body"
  hx-swap="innerHTML">
  Edit
</button>

JavaScript (Calendar setup and HTMX config)

eventClick: function(info) {
  fetch(`/events/${info.event.id}/detail/`)
    .then(response => response.json())
    .then(data => {
      const target = document.getElementById('event-modal-body');
      target.innerHTML = data.html;
      if (window.htmx) {
        htmx.process(target);
      }
      new bootstrap.Modal(document.getElementById('eventModal')).show();
    });
  info.jsEvent.preventDefault();
}

HTMX config in base.html:

document.body.addEventListener('htmx:configRequest', function (event) {
  const csrfInput = document.querySelector('[name=csrfmiddlewaretoken]');
  if (csrfInput) {
    event.detail.headers['X-CSRFToken'] = csrfInput.value;
  }
});

Relevant Views:

from django.shortcuts import render, get_object_or_404
from django.http import JsonResponse
from .models import Event
from .forms import EventForm

def event_detail_json(request, event_id):
    """
    Returns event detail as JSON with rendered HTML partial for modal.
    """
    event = get_object_or_404(Event, pk=event_id)
    html = render(request, "mncanoe/_event_detail.html", {"event": event}).content.decode("utf-8")
    return JsonResponse({"html": html})

def event_edit_partial(request, event_id):
    """
    Handles GET (load edit form) and POST (save edit) via HTMX.
    """
    event = get_object_or_404(Event, pk=event_id)
    if request.method == "POST":
        form = EventForm(request.POST, instance=event)
        if form.is_valid():
            form.save()
            return JsonResponse({"success": True})
        else:
            html = render(request, "mncanoe/_event_form.html", {
                "form": form,
                "form_action": request.path,
            }).content.decode("utf-8")
            return JsonResponse({"html": html})
    else:
        # GET: render form for editing
        form = EventForm(instance=event)
        html = render(request, "mncanoe/_event_form.html", {
            "form": form,
            "form_action": request.path,
        }).content.decode("utf-8")
        return JsonResponse({"html": html})

def event_form(request):
    """
    For creating a new event (via HTMX modal).
    """
    if request.method == "POST":
        form = EventForm(request.POST)
        if form.is_valid():
            form.save()
            return JsonResponse({"success": True})
        else:
            html = render(request, "mncanoe/_event_form.html", {
                "form": form,
                "form_action": request.path,
            }).content.decode("utf-8")
            return JsonResponse({"html": html})
    else:
        form = EventForm()
        html = render(request, "mncanoe/_event_form.html", {
            "form": form,
            "form_action": request.path,
        }).content.decode("utf-8")
        return JsonResponse({"html": html})

What happens:

  • Clicking Edit in the modal loads the form just fine via HTMX.
  • When I click Save Event on the edit form:
    • The request is a GET, not a POST.
    • The event_edit_partial view is called with a GET, so nothing saves.
    • Network/console confirms no POST is being sent for that form submission.

What I’ve Tried:

  • Confirmed the form is rendered as <form method="POST" hx-post="..."> (I checked rendered HTML).
  • {% csrf_token %} is present.
  • No JavaScript errors in console.
  • HTMX is loaded and working (other htmx requests work).
  • Changing hx-swap/target options, no difference.
  • Reproduced in both Chrome and Edge, with cache cleared.

Any ideas or pointers are much appreciated!
Let me know if you need my views code as well.


Thank you!

It would probably be helpful to see the html as it exists in the browser when the submit button is being pushed.

this is the full html page just before “Save Event” button is clicked. I am breaking it out into two posts, because it is too long

Part1:

<html lang="en"><head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Event Calendar</title>

  <style data-fullcalendar=""></style><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" rel="stylesheet">



  <style>
    /* Base styles */
    body {
      margin: 0;
      font-family: Arial, sans-serif;
      background-color: #f9f9f9;
    }
    header {
      background-color: #ffffff;
      padding: 0.75rem 1rem;
      color: #333;
      display: flex;
      align-items: center;
      justify-content: space-between;
      position: relative;
      box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    }
    .brand {
      display: flex;
      align-items: center;
      gap: 0.5rem;
    }
    .brand img {
      height: 80px;
      width: auto;
    }
    nav {
      display: flex;
      gap: 1.5rem;
    }
    nav a {
      color: #333;
      text-decoration: none;
      position: relative;
      padding: 0.25rem 0;
      font-weight: 500;
      transition: color 0.3s ease;
    }
    nav a::after {
      content: '';
      position: absolute;
      width: 0%;
      height: 2px;
      bottom: 0;
      left: 0;
      background-color: #333;
      transition: width 0.3s ease;
    }
    nav a:hover {
      color: #555;
    }
    nav a:hover::after {
      width: 100%;
    }
    .menu-toggle {
      display: none;
      flex-direction: column;
      cursor: pointer;
    }
    .menu-toggle span {
      height: 3px;
      width: 25px;
      background: #333;
      margin: 4px 0;
      transition: 0.4s;
    }
    .nav-links {
      display: flex;
      gap: 1.5rem;
    }

    /* Mobile styles */
    @media (max-width: 768px) {
      .menu-toggle {
        display: flex;
      }
      .nav-links {
        display: none;
        flex-direction: column;
        background-color: #ffffff;
        position: absolute;
        top: 60px;
        right: 0;
        width: 220px;
        padding: 1rem;
        box-shadow: 0 2px 8px rgba(0,0,0,0.2);
      }
      .nav-links a {
        color: #333;
        border-bottom: 1px solid #eee;
        padding: 0.5rem 0;
      }
      .nav-links.active {
        display: flex;
      }
    }

    .btn-login, .btn-logout {
      padding: 0.5rem 1rem;
      border: 1px solid #333;
      border-radius: 4px;
      text-decoration: none;
      color: #333;
      transition: background-color 0.3s;
    }

    .btn-login:hover, .btn-logout:hover {
      background-color: #eee;
    }


.hero-two-column {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  padding: 4rem 2rem;
  background-color: #f5f5f5;
}

.hero-two-column .hero-text {
  flex: 1 1 400px;
  max-width: 800px;
  padding: 2rem;
}

.hero-two-column .hero-text h1 {
  font-size: 3rem;
  margin-bottom: 1rem;
}

.hero-two-column .hero-text p {
  font-size: 1.25rem;
  margin-bottom: 2rem;
}

.hero-two-column .btn {
  display: inline-block;
  padding: 0.75rem 1.5rem;
  background-color: #007bff;
  color: white;
  text-decoration: none;
  border-radius: 4px;
}

.hero-two-column .btn:hover {
  background-color: #0056b3;
}

.hero-two-column .hero-image {
  flex: 1 1 500px;
  max-width: 800px;
  padding: 2rem;
  text-align: center;
}

.hero-two-column .hero-image img {
  max-width: 100%;
  height: auto;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

/* Responsive */
@media (max-width: 768px) {
  .hero-two-column {
    flex-direction: column;
  }
  .hero-two-column .hero-text,
  .hero-two-column .hero-image {
    max-width: 100%;
    padding: 1rem;
  }
}

.bg-gray {
  background-color: #bfbfbf;
}

  </style>

  <style>
    #calendar {
      max-width: 900px;
      margin: 2rem auto;
      background: #fff;
      padding: 1rem;
      box-shadow: 0 2px 8px rgba(0,0,0,0.1);
      border-radius: 8px;
    }
</style>


  


<style>                      .htmx-indicator{opacity:0}                      .htmx-request .htmx-indicator{opacity:1; transition: opacity 200ms ease-in;}                      .htmx-request.htmx-indicator{opacity:1; transition: opacity 200ms ease-in;}                    </style></head>
<body class="modal-open" style="overflow: hidden; padding-right: 19px;">
    <script src="https://unpkg.com/htmx.org@1.9.10/dist/htmx.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/fullcalendar@6.1.11/index.global.min.js"></script>

  <header>
    <div class="brand">
      <a href="/">
        <img src="/static/mncanoe/images/mca_logo.png" alt="MN Canoe Logo">
      </a>
    </div>
    <div class="menu-toggle" onclick="toggleMenu()">
      <span></span>
      <span></span>
      <span></span>
    </div>
    <nav class="nav-links" id="navLinks">
      <a href="/">Home</a>
      <a href="#">About</a>
      <a href="/rookies/">Rookies</a>
      <a href="/calendar/">Calendar</a>
      <a href="#">Contact</a>

  
    <a class="btn-login" href="/accounts/login/">Login</a>
  

    </nav>
  </header>

Part 2:

  <main>
    
  <h2 class="text-center my-4">Event Calendar</h2>

  <!-- ✅ Calendar container -->
  <div id="calendar" style="max-width: 900px; margin: 2rem auto;" class="fc fc-media-screen fc-direction-ltr fc-theme-standard"><div class="fc-header-toolbar fc-toolbar fc-toolbar-ltr"><div class="fc-toolbar-chunk"><div class="fc-button-group"><button type="button" title="Previous month" aria-pressed="false" class="fc-prev-button fc-button fc-button-primary"><span class="fc-icon fc-icon-chevron-left" role="img"></span></button><button type="button" title="Next month" aria-pressed="false" class="fc-next-button fc-button fc-button-primary"><span class="fc-icon fc-icon-chevron-right" role="img"></span></button></div><button type="button" title="This month" disabled="" aria-pressed="false" class="fc-today-button fc-button fc-button-primary">today</button></div><div class="fc-toolbar-chunk"><h2 class="fc-toolbar-title" id="fc-dom-1">July 2025</h2></div><div class="fc-toolbar-chunk"><div class="fc-button-group"><button type="button" title="month view" aria-pressed="true" class="fc-dayGridMonth-button fc-button fc-button-primary fc-button-active">month</button><button type="button" title="week view" aria-pressed="false" class="fc-timeGridWeek-button fc-button fc-button-primary">week</button><button type="button" title="day view" aria-pressed="false" class="fc-timeGridDay-button fc-button fc-button-primary">day</button><button type="button" title="list view" aria-pressed="false" class="fc-listWeek-button fc-button fc-button-primary">list</button></div></div></div><div aria-labelledby="fc-dom-1" class="fc-view-harness fc-view-harness-active" style="height: 577.037px;"><div class="fc-dayGridMonth-view fc-view fc-daygrid"><table role="grid" class="fc-scrollgrid  fc-scrollgrid-liquid"><thead role="rowgroup"><tr role="presentation" class="fc-scrollgrid-section fc-scrollgrid-section-header "><th role="presentation"><div class="fc-scroller-harness"><div class="fc-scroller" style="overflow: hidden;"><table role="presentation" class="fc-col-header " style="width: 777px;"><colgroup></colgroup><thead role="presentation"><tr role="row"><th role="columnheader" class="fc-col-header-cell fc-day fc-day-sun"><div class="fc-scrollgrid-sync-inner"><a aria-label="Sunday" class="fc-col-header-cell-cushion">Sun</a></div></th><th role="columnheader" class="fc-col-header-cell fc-day fc-day-mon"><div class="fc-scrollgrid-sync-inner"><a aria-label="Monday" class="fc-col-header-cell-cushion">Mon</a></div></th><th role="columnheader" class="fc-col-header-cell fc-day fc-day-tue"><div class="fc-scrollgrid-sync-inner"><a aria-label="Tuesday" class="fc-col-header-cell-cushion">Tue</a></div></th><th role="columnheader" class="fc-col-header-cell fc-day fc-day-wed"><div class="fc-scrollgrid-sync-inner"><a aria-label="Wednesday" class="fc-col-header-cell-cushion">Wed</a></div></th><th role="columnheader" class="fc-col-header-cell fc-day fc-day-thu"><div class="fc-scrollgrid-sync-inner"><a aria-label="Thursday" class="fc-col-header-cell-cushion">Thu</a></div></th><th role="columnheader" class="fc-col-header-cell fc-day fc-day-fri"><div class="fc-scrollgrid-sync-inner"><a aria-label="Friday" class="fc-col-header-cell-cushion">Fri</a></div></th><th role="columnheader" class="fc-col-header-cell fc-day fc-day-sat"><div class="fc-scrollgrid-sync-inner"><a aria-label="Saturday" class="fc-col-header-cell-cushion">Sat</a></div></th></tr></thead></table></div></div></th></tr></thead><tbody role="rowgroup"><tr role="presentation" class="fc-scrollgrid-section fc-scrollgrid-section-body  fc-scrollgrid-section-liquid"><td role="presentation"><div class="fc-scroller-harness fc-scroller-harness-liquid"><div class="fc-scroller fc-scroller-liquid-absolute" style="overflow: hidden auto;"><div class="fc-daygrid-body fc-daygrid-body-unbalanced " style="width: 777px;"><table role="presentation" class="fc-scrollgrid-sync-table" style="width: 777px; height: 546px;"><colgroup></colgroup><tbody role="presentation"><tr role="row"><td aria-labelledby="fc-dom-2" role="gridcell" data-date="2025-06-29" class="fc-day fc-day-sun fc-day-past fc-day-other fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to June 29, 2025" data-navlink="" tabindex="0" id="fc-dom-2" class="fc-daygrid-day-number">29</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-4" role="gridcell" data-date="2025-06-30" class="fc-day fc-day-mon fc-day-past fc-day-other fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to June 30, 2025" data-navlink="" tabindex="0" id="fc-dom-4" class="fc-daygrid-day-number">30</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-6" role="gridcell" data-date="2025-07-01" class="fc-day fc-day-tue fc-day-past fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 1, 2025" data-navlink="" tabindex="0" id="fc-dom-6" class="fc-daygrid-day-number">1</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-8" role="gridcell" data-date="2025-07-02" class="fc-day fc-day-wed fc-day-past fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 2, 2025" data-navlink="" tabindex="0" id="fc-dom-8" class="fc-daygrid-day-number">2</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-10" role="gridcell" data-date="2025-07-03" class="fc-day fc-day-thu fc-day-past fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 3, 2025" data-navlink="" tabindex="0" id="fc-dom-10" class="fc-daygrid-day-number">3</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-12" role="gridcell" data-date="2025-07-04" class="fc-day fc-day-fri fc-day-past fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 4, 2025" data-navlink="" tabindex="0" id="fc-dom-12" class="fc-daygrid-day-number">4</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-14" role="gridcell" data-date="2025-07-05" class="fc-day fc-day-sat fc-day-past fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 5, 2025" data-navlink="" tabindex="0" id="fc-dom-14" class="fc-daygrid-day-number">5</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td></tr><tr role="row"><td aria-labelledby="fc-dom-16" role="gridcell" data-date="2025-07-06" class="fc-day fc-day-sun fc-day-past fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 6, 2025" data-navlink="" tabindex="0" id="fc-dom-16" class="fc-daygrid-day-number">6</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-18" role="gridcell" data-date="2025-07-07" class="fc-day fc-day-mon fc-day-past fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 7, 2025" data-navlink="" tabindex="0" id="fc-dom-18" class="fc-daygrid-day-number">7</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-20" role="gridcell" data-date="2025-07-08" class="fc-day fc-day-tue fc-day-past fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 8, 2025" data-navlink="" tabindex="0" id="fc-dom-20" class="fc-daygrid-day-number">8</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-22" role="gridcell" data-date="2025-07-09" class="fc-day fc-day-wed fc-day-past fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 9, 2025" data-navlink="" tabindex="0" id="fc-dom-22" class="fc-daygrid-day-number">9</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-24" role="gridcell" data-date="2025-07-10" class="fc-day fc-day-thu fc-day-past fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 10, 2025" data-navlink="" tabindex="0" id="fc-dom-24" class="fc-daygrid-day-number">10</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-26" role="gridcell" data-date="2025-07-11" class="fc-day fc-day-fri fc-day-past fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 11, 2025" data-navlink="" tabindex="0" id="fc-dom-26" class="fc-daygrid-day-number">11</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-event-harness" style="margin-top: 0px;"><a tabindex="0" class="fc-event fc-event-start fc-event-end fc-event-past fc-daygrid-event fc-daygrid-dot-event"><div class="fc-daygrid-event-dot"></div><div class="fc-event-time">7a</div><div class="fc-event-title">test9</div></a></div><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-28" role="gridcell" data-date="2025-07-12" class="fc-day fc-day-sat fc-day-past fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 12, 2025" data-navlink="" tabindex="0" id="fc-dom-28" class="fc-daygrid-day-number">12</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td></tr><tr role="row"><td aria-labelledby="fc-dom-30" role="gridcell" data-date="2025-07-13" class="fc-day fc-day-sun fc-day-past fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 13, 2025" data-navlink="" tabindex="0" id="fc-dom-30" class="fc-daygrid-day-number">13</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-32" role="gridcell" data-date="2025-07-14" class="fc-day fc-day-mon fc-day-past fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 14, 2025" data-navlink="" tabindex="0" id="fc-dom-32" class="fc-daygrid-day-number">14</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-34" role="gridcell" data-date="2025-07-15" class="fc-day fc-day-tue fc-day-past fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 15, 2025" data-navlink="" tabindex="0" id="fc-dom-34" class="fc-daygrid-day-number">15</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-36" role="gridcell" data-date="2025-07-16" class="fc-day fc-day-wed fc-day-past fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 16, 2025" data-navlink="" tabindex="0" id="fc-dom-36" class="fc-daygrid-day-number">16</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-38" role="gridcell" data-date="2025-07-17" class="fc-day fc-day-thu fc-day-past fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 17, 2025" data-navlink="" tabindex="0" id="fc-dom-38" class="fc-daygrid-day-number">17</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-40" role="gridcell" data-date="2025-07-18" class="fc-day fc-day-fri fc-day-past fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 18, 2025" data-navlink="" tabindex="0" id="fc-dom-40" class="fc-daygrid-day-number">18</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-event-harness" style="margin-top: 0px;"><a tabindex="0" class="fc-event fc-event-start fc-event-end fc-event-past fc-daygrid-event fc-daygrid-dot-event"><div class="fc-daygrid-event-dot"></div><div class="fc-event-time">7a</div><div class="fc-event-title">testsd</div></a></div><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-42" role="gridcell" data-date="2025-07-19" class="fc-day fc-day-sat fc-day-today fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 19, 2025" data-navlink="" tabindex="0" id="fc-dom-42" class="fc-daygrid-day-number">19</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td></tr><tr role="row"><td aria-labelledby="fc-dom-44" role="gridcell" data-date="2025-07-20" class="fc-day fc-day-sun fc-day-future fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 20, 2025" data-navlink="" tabindex="0" id="fc-dom-44" class="fc-daygrid-day-number">20</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-46" role="gridcell" data-date="2025-07-21" class="fc-day fc-day-mon fc-day-future fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 21, 2025" data-navlink="" tabindex="0" id="fc-dom-46" class="fc-daygrid-day-number">21</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-48" role="gridcell" data-date="2025-07-22" class="fc-day fc-day-tue fc-day-future fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 22, 2025" data-navlink="" tabindex="0" id="fc-dom-48" class="fc-daygrid-day-number">22</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-50" role="gridcell" data-date="2025-07-23" class="fc-day fc-day-wed fc-day-future fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 23, 2025" data-navlink="" tabindex="0" id="fc-dom-50" class="fc-daygrid-day-number">23</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-52" role="gridcell" data-date="2025-07-24" class="fc-day fc-day-thu fc-day-future fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 24, 2025" data-navlink="" tabindex="0" id="fc-dom-52" class="fc-daygrid-day-number">24</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-54" role="gridcell" data-date="2025-07-25" class="fc-day fc-day-fri fc-day-future fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 25, 2025" data-navlink="" tabindex="0" id="fc-dom-54" class="fc-daygrid-day-number">25</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-event-harness" style="margin-top: 0px;"><a tabindex="0" class="fc-event fc-event-start fc-event-end fc-event-future fc-daygrid-event fc-daygrid-dot-event"><div class="fc-daygrid-event-dot"></div><div class="fc-event-time">7a</div><div class="fc-event-title">canoe race</div></a></div><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-56" role="gridcell" data-date="2025-07-26" class="fc-day fc-day-sat fc-day-future fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 26, 2025" data-navlink="" tabindex="0" id="fc-dom-56" class="fc-daygrid-day-number">26</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td></tr><tr role="row"><td aria-labelledby="fc-dom-58" role="gridcell" data-date="2025-07-27" class="fc-day fc-day-sun fc-day-future fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 27, 2025" data-navlink="" tabindex="0" id="fc-dom-58" class="fc-daygrid-day-number">27</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-60" role="gridcell" data-date="2025-07-28" class="fc-day fc-day-mon fc-day-future fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 28, 2025" data-navlink="" tabindex="0" id="fc-dom-60" class="fc-daygrid-day-number">28</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-62" role="gridcell" data-date="2025-07-29" class="fc-day fc-day-tue fc-day-future fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 29, 2025" data-navlink="" tabindex="0" id="fc-dom-62" class="fc-daygrid-day-number">29</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-64" role="gridcell" data-date="2025-07-30" class="fc-day fc-day-wed fc-day-future fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 30, 2025" data-navlink="" tabindex="0" id="fc-dom-64" class="fc-daygrid-day-number">30</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-66" role="gridcell" data-date="2025-07-31" class="fc-day fc-day-thu fc-day-future fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to July 31, 2025" data-navlink="" tabindex="0" id="fc-dom-66" class="fc-daygrid-day-number">31</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-68" role="gridcell" data-date="2025-08-01" class="fc-day fc-day-fri fc-day-future fc-day-other fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to August 1, 2025" data-navlink="" tabindex="0" id="fc-dom-68" class="fc-daygrid-day-number">1</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-70" role="gridcell" data-date="2025-08-02" class="fc-day fc-day-sat fc-day-future fc-day-other fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to August 2, 2025" data-navlink="" tabindex="0" id="fc-dom-70" class="fc-daygrid-day-number">2</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td></tr><tr role="row"><td aria-labelledby="fc-dom-72" role="gridcell" data-date="2025-08-03" class="fc-day fc-day-sun fc-day-future fc-day-other fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to August 3, 2025" data-navlink="" tabindex="0" id="fc-dom-72" class="fc-daygrid-day-number">3</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-74" role="gridcell" data-date="2025-08-04" class="fc-day fc-day-mon fc-day-future fc-day-other fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to August 4, 2025" data-navlink="" tabindex="0" id="fc-dom-74" class="fc-daygrid-day-number">4</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-76" role="gridcell" data-date="2025-08-05" class="fc-day fc-day-tue fc-day-future fc-day-other fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to August 5, 2025" data-navlink="" tabindex="0" id="fc-dom-76" class="fc-daygrid-day-number">5</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-78" role="gridcell" data-date="2025-08-06" class="fc-day fc-day-wed fc-day-future fc-day-other fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to August 6, 2025" data-navlink="" tabindex="0" id="fc-dom-78" class="fc-daygrid-day-number">6</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-80" role="gridcell" data-date="2025-08-07" class="fc-day fc-day-thu fc-day-future fc-day-other fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to August 7, 2025" data-navlink="" tabindex="0" id="fc-dom-80" class="fc-daygrid-day-number">7</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-82" role="gridcell" data-date="2025-08-08" class="fc-day fc-day-fri fc-day-future fc-day-other fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to August 8, 2025" data-navlink="" tabindex="0" id="fc-dom-82" class="fc-daygrid-day-number">8</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td><td aria-labelledby="fc-dom-84" role="gridcell" data-date="2025-08-09" class="fc-day fc-day-sat fc-day-future fc-day-other fc-daygrid-day"><div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner"><div class="fc-daygrid-day-top"><a title="Go to August 9, 2025" data-navlink="" tabindex="0" id="fc-dom-84" class="fc-daygrid-day-number">9</a></div><div class="fc-daygrid-day-events"><div class="fc-daygrid-day-bottom" style="margin-top: 0px;"></div></div><div class="fc-daygrid-day-bg"></div></div></td></tr></tbody></table></div></div></div></td></tr></tbody></table></div></div></div>

  <!-- ✅ Modal for Event Form -->
  <div class="modal fade show" id="eventModal" tabindex="-1" aria-modal="true" role="dialog" style="display: block;">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title">Add Event</h5>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
        <div class="modal-body" id="event-modal-body"><form id="event-form" method="POST" hx-post="/events/2/edit/" hx-target="#event-modal-body" hx-swap="innerHTML">
  <input type="hidden" name="csrfmiddlewaretoken" value="Eh5BHE2glhjpv2kQxeryiDGnJnPQL4EKun5zICxcEuQb6IJJXPPJaOybJvNZ6jl5">
  <p>
    <label for="id_title">Title:</label>
    <input type="text" name="title" value="test9" maxlength="200" class="form-control" required="" id="id_title">
    
    
  </p>

  
  <p>
    <label for="id_description">Description:</label>
    <textarea name="description" cols="40" rows="10" class="form-control" id="id_description"></textarea>
    
    
  </p>

  
  <p>
    <label for="id_start">Start:</label>
    <input type="datetime-local" name="start" value="2025-07-11 12:00:00" class="form-control" required="" id="id_start">
    
    
  </p>

  
  <p>
    <label for="id_end">End:</label>
    <input type="datetime-local" name="end" value="2025-07-11 13:00:00" class="form-control" required="" id="id_end">
    
    
  </p>

  
  <p>
    <label for="id_location">Location:</label>
    <input type="text" name="location" maxlength="200" class="form-control" id="id_location">
    
    
      
    
  </p>

  <div class="d-grid gap-2">
    <button type="submit" class="btn btn-primary">Save Event</button>
    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
  </div>
</form>
</div>
      </div>
    </div>
  </div>


    



  <!-- ✅ Calendar initialization -->
  <script>
    document.addEventListener('DOMContentLoaded', function() {
      var calendarEl = document.getElementById('calendar');
      var calendar = new FullCalendar.Calendar(calendarEl, {
        initialView: 'dayGridMonth',
        headerToolbar: {
          left: 'prev,next today',
          center: 'title',
          right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
        },
        navLinks: true,
        editable: false,
        selectable: false,
        events: '/events/json/',



        eventClick: function(info) {
          fetch(`/events/${info.event.id}/detail/`)
            .then(response => response.json())
            .then(data => {
              const target = document.getElementById('event-modal-body');
              target.innerHTML = data.html;
              if (window.htmx) {
                htmx.process(target);
              }
              new bootstrap.Modal(document.getElementById('eventModal')).show();
            })
            .catch(error => {
              console.error('Error loading event detail:', error);
              alert('Error loading event detail. Check console.');
            });

          info.jsEvent.preventDefault();
        },





        dateClick: function(info) {
          fetch("/events/form/?start=" + encodeURIComponent(info.dateStr))
            .then(response => {
              if (!response.ok) throw new Error('Network error');
              return response.json();
            })
            .then(data => {
              if (data.html) {
                const target = document.getElementById('event-modal-body');
                target.innerHTML = data.html;

                if (window.htmx) {
                  htmx.process(target);
                }

                new bootstrap.Modal(document.getElementById('eventModal')).show();
              } else {
                console.error('No HTML in JSON response:', data);
                alert('Failed to load form. Check console.');
              }
            })
            .catch(error => {
              console.error('Error fetching form:', error);
              alert('Error loading form. Check console for details.');
            });
        },

      });
      calendar.render();

      // ✅ Listen for HTMX form submission responses
    document.body.addEventListener('htmx:afterRequest', function(evt) {
      try {
        var response = JSON.parse(evt.detail.xhr.responseText);
        if (response.success) {
          bootstrap.Modal.getInstance(document.getElementById('eventModal')).hide();
          calendar.refetchEvents();
        } else if (response.html) {
          document.getElementById('event-modal-body').innerHTML = response.html;
        }
      } catch (e) {
        console.error('Error parsing HTMX response:', e);
      }
    });

    });


    document.body.addEventListener("htmx:afterSwap", (e) => {
  if (e.detail.target.id === "event-modal-body") {
    console.log("HTMX reprocessed modal body");
    htmx.process(e.detail.target);  // Ensure HTMX wires up the form
  }
});

  </script>

  </main>
  <script>
    function toggleMenu() {
      document.getElementById('navLinks').classList.toggle('active');
    }
  </script>



    <script>
      document.body.addEventListener('htmx:configRequest', function (event) {
        const csrfInput = document.querySelector('[name=csrfmiddlewaretoken]');
        if (csrfInput) {
          event.detail.headers['X-CSRFToken'] = csrfInput.value;
        }
      });
    </script>








<div class="modal-backdrop fade show"></div></body></html>