How to create a Django form in 2mins using Alpine.js 🏔️
Published: July 27, 2023
There will be 4 steps. Each takes under 30 seconds.
We'll assume that you've already setup your Django
project
and created an app (I'll be using one I named sim
). You don't need to
know anything about
Alpine.js
. I'll walk you through.
My video follows the guide below. Let's get to it!
1. Create template
- create a folder called
templates
in yoursim
app - add an html file, we'll call it example.html
- add your form html to the template
<div><form><div><input name="email" type="email" /><input name="codename" type="text" /><input name="dress_color" type="color" /><button>Submit</button></div><div><p>Successfully submitted form ✅</p></div><div><p>Error submitting your form ❌</p></div></form></div>
2. Add your Django view
- Add your view, update your urls, and check that a template is rendered at the right url.
# views.pyfrom django.shortcuts import renderdef example(request):return render(request, 'templates/example.html', context={})def sample_post(request):data = request.POSTprint(f'{data = }')return JsonResponse({'status': 'success'})# urls.pyfrom . import viewsfrom django.urls import pathurlpatterns = [path('example', views.example, name='example'),path('sample-post/', views.sample_post, name='sample_post')]
3. Add alpine js to template
- Add Alpine js submit function
- include the Django CSRF token
- add your specific view url path
- Add Alpine js syntax to control the form and manage the form's state
- Add Alpine js loader script using a CDN (very fast and light)
<div><form @submit.prevent="submit" x-data="{ status: 'normal', errors: {} }"><div x-show="status === 'normal'"><input name="email" type="email" /><input name="codename" type="text" /><input name="dress_color" type="color" /><button>Submit</button></div><div x-show="status === 'success'"><p>Successfully submitted form ✅</p></div><div x-show="status === 'error'"><p>Error submitting your form ❌</p></div></form></div><script>function submit(event) {event.preventDefault()const formData = new FormData(event.target)// Update the `endpointUrl` to your specific url below.const endpointUrl = '/sample-post/'fetch(endpointUrl, {method: 'post',body: formData,headers: {'X-CSRFToken': '{{ csrf_token }}',},}).then((response) => {this.status = response.ok ? 'success' : 'error'return response.json()}).then((data) => {this.errors = data.errors || {}})}</script><scriptdefer=""src="https://cdn.jsdelivr.net/npm/alpinejs@3.12.3/dist/cdn.min.js"></script>
4. Check that the view works as expected
- Submit something.
- Check in the Django run console that you see something like:
data = {"email": ..., "codename": ..., "dress_color":...}
Bonus: Prevent form flickering due to alpine loading
- Add x-cloak to the form. This will hide the form until it's finished loading (avoiding flicker).
- Add x-cloak into the style tag (or add a similar line to any stylesheet that you are using)
<div><formx-cloak@submit.prevent="submit"x-data="{ status: 'normal', errors: {} }"><div x-show="status === 'normal'"><input name="email" type="email" /><input name="codename" type="text" /><input name="dress_color" type="color" /><button>Submit</button></div><div x-show="status === 'success'"><p>Successfully submitted form ✅</p></div><div x-show="status === 'error'"><p>Error submitting your form ❌</p></div></form></div><script>function submit(event) {event.preventDefault()const formData = new FormData(event.target)// Update the `endpointUrl` to your specific url below.const endpointUrl = '/sample-post/'fetch(endpointUrl, {method: 'post',body: formData,headers: {'X-CSRFToken': '{{ csrf_token }}',},}).then((response) => {this.status = response.ok ? 'success' : 'error'return response.json()}).then((data) => {this.errors = data.errors || {}})}</script><scriptdefer=""src="https://cdn.jsdelivr.net/npm/alpinejs@3.12.3/dist/cdn.min.js"></script><style>[x-cloak] {display: none !important;}</style>
Congratulations! Using Alpine.js is a neat, clean way to add simple JavaScript, including managing state, to your Django templates.