Skip to content

Commit

Permalink
58 - Saving Dynamic List View Changes with HTMX
Browse files Browse the repository at this point in the history
  • Loading branch information
codingforentrepreneurs committed Jan 12, 2024
1 parent 296160d commit 7910439
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 9 deletions.
4 changes: 4 additions & 0 deletions src/items/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
from .models import Item


class ItemPatchForm(forms.Form):
title = forms.CharField(required=False)
status = forms.CharField(required=False)

class ItemCreateForm(forms.ModelForm):
class Meta:
model = Item
Expand Down
27 changes: 27 additions & 0 deletions src/items/views.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.contrib.auth.decorators import login_required
from django.http import QueryDict
from django.shortcuts import redirect, render, get_object_or_404
from django.urls import reverse
from projects import cache as projects_cache
Expand Down Expand Up @@ -26,8 +27,34 @@ def item_detail_inline_update_view(request, id=None):
if not request.htmx:
detail_url = instance.get_absolute_url()
return redirect(detail_url)

template_name = "items/snippets/table-row-edit.html"
success_template = "items/snippets/table-row.html"
if f"{request.method}".lower() == "patch":
query_dict = QueryDict(request.body)
data = query_dict.dict()
form = forms.ItemPatchForm(data)
if form.is_valid():
valid_data = form.cleaned_data
changed = False
for k, v in valid_data.items():
changed = True
if v == "":
continue
if not v:
continue
setattr(instance, k , v)
if changed:
instance.save()
template_name = success_template
choices = Item.ItemStatus.choices
context = {
"instance": instance,
"choices": choices,
"form": form,
}
return render(request, template_name, context)

form = forms.ItemInlineForm(request.POST or None, instance=instance)
if form.is_valid():
item_obj = form.save(commit=False)
Expand Down
15 changes: 15 additions & 0 deletions src/static/css/cfehome-ui.css
Original file line number Diff line number Diff line change
Expand Up @@ -1984,6 +1984,11 @@ input:checked + .toggle-bg {
padding-bottom: 2rem;
}

.px-0 {
padding-left: 0px;
padding-right: 0px;
}

.pr-4 {
padding-right: 1rem;
}
Expand Down Expand Up @@ -2224,6 +2229,10 @@ input:checked + .toggle-bg {
color: rgb(17 24 39 / var(--tw-text-opacity));
}

.focus\:border-0:focus {
border-width: 0px;
}

.focus\:border-blue-500:focus {
--tw-border-opacity: 1;
border-color: rgb(63 131 248 / var(--tw-border-opacity));
Expand Down Expand Up @@ -2251,6 +2260,12 @@ input:checked + .toggle-bg {
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}

.focus\:ring-0:focus {
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}

.focus\:\!ring-primary-300:focus {
--tw-ring-opacity: 1 !important;
--tw-ring-color: rgb(147 197 253 / var(--tw-ring-opacity)) !important;
Expand Down
8 changes: 7 additions & 1 deletion src/templates/items/snippets/status-select.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
<select id="countries" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
<select name="status"
hx-patch="{{ instance.get_edit_url }}"
hx-trigger="change"
hx-target="#item-table-row-{{ instance.id }}"
hx-swap="outerHTML"
id="countries"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
{% for choice in choices %}
<option value="{{ choice.0 }}" {% if instance.status == choice.0 %} selected {% endif %}>{{ choice.1 }}</option>
{% endfor %}
Expand Down
19 changes: 11 additions & 8 deletions src/templates/items/snippets/table-row.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,17 @@
id="item-table-row-{{ instance.id }}"
>
<th scope="row" class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
{{ instance.title }}
</th>
<input
type="text"
name="title"
hx-patch="{{ instance.get_edit_url }}"
hx-trigger="keyup changed delay:1s"
hx-target="#item-table-row-{{ instance.id }}"
hx-swap="outerHTML"
value="{{ instance.title}}"
class="focus:border-0 focus:ring-0 border-0 px-0"
/>
</th>
<td class="px-6 py-4">
{% item_status_select instance %}
</td>
Expand All @@ -13,12 +22,6 @@
</td>
<td class="px-6 py-4">
<a href="{{ instance.get_absolute_url }}">View</a>

<button
hx-swap="outerHTML"
hx-target="#item-table-row-{{ instance.id }}"
hx-get="{{ instance.get_edit_url }}">Edit</button>

<button
hx-confirm="Are you sure you want to delete this?"
hx-post="{{ instance.get_delete_url }}">Delete</button>
Expand Down

0 comments on commit 7910439

Please sign in to comment.