Code Monkey home page Code Monkey logo

okayjack-htmx's Introduction

Okayjack (Django+htmx)

Okayjack (+django-render-blocks) extends Django and htmx a smidge so they are even more pleasant to use! 🥳

  1. Extends htmx by moving all htmx logic to the request markup by default

    1. Which template or DTL block to use for a response
    2. How to handle a successful (valid) form submission vs an errorenous (invalid) ones
    3. Triggering an action after a response is received
  2. Extends Django's REST verbs support (adds a body to PATCH etc)

Codewise, Okayjack is:

  1. Some Django middleware
  2. A few HttpResponse classes
  3. A htmx JavaScript extension.

Farside comic

Overview

htmx extension

Normal htmx requests - with a bit of Django form error display - look something like this

<form hx-post="/store">
	
	<input id="title" name="title" type="text" {% if form.title.errors %}class="error"{% endif %}>
	{% if form.title.errors %}
		<div class='error'>{{ form.title.errors }}</div>
	{% endif %}
	<button type="submit">Submit</button>

</form>

With Okayjack, you can do this.

{% block title_form %}
	<form 
		hx-post="/store"
		hx-success-target="h1"
		hx-success-swap="outerHTML"
		hx-success-block="this-example-file.html:title_success"
		hx-error-block="this-example-file.html:title_form">

			<input id="title" name="title" type="text" {% if form.title.errors %}class="error"{% endif %}>
			{% if form.title.errors %}
				<div class='error'>{{ form.title.errors }}</div>
			{% endif %}
			<button type="submit">Submit</button>

	</form>
{% endblock %}

<template>
	{% block title_success %}
		<h1>{{ title }}</h1>
	{% endblock %}
</template>

This example shows the blocks in the same file as the requesting html. The blocks can actually be in any file however.

Django middleware and response classes

Given the above HTML, in the corresponding Django view, we now only have to do the following to handle both success and error variations.

def title(request, question_id):
	form = TitleForm(request.POST)
	if form.is_valid():
		form.save()
		return HxSuccessResponse(request, {'form': form)
	return HxErrorResponse(request, {'form': form})

Installation

  1. pip install django-render-blocks

  2. Add okayjack app to Django project

INSTALLED_APPS = [
    ...
    'render_block',
    'okayjack',
]
MIDDLEWARE = [
    ...
	'okayjack.middleware.OkayjackMiddleware',
]
  1. Import okayjack.http in your views.py to use the HttpResponse-like classes

  2. Load htmx extension https://htmx.org/attributes/hx-ext/ in template

API

htmx extension

Supports all htmx response headers https://htmx.org/reference/#response_headers.

You can use a combination of:

  • Regular hx-* attributes. E.g. hx-target="..."
  • Regular hx-success-* attributes - used when Django returns a HxSuccessResponse. E.g. hx-success-target="..."
  • Regular hx-error-* attributes - used when Django returns a HxErrorResponse. E.g. hx-error-target="..."

htmx will use the values of hx-* unless there is a hx-success-* or hx-error-* value (for a success or error response respectively).

The * in hx-success-* and hx-error-* attributes can be any of the following.

  • location
  • push-url
  • redirect
  • refresh
  • replace-url
  • swap
  • target
  • trigger-after-receive
  • trigger-after-settle
  • trigger-after-swap
  • block

trigger-after-receive isn't a normal htmx attribute. It sets the HX-Trigger response header. It had to be renamed so it doesn't conflict with hx-trigger for triggering the request itself 🤷

block is the path to a template and optional template block to use when generating the HTML response. E.g.

hx-block="base/home.html:welcome_block" or hx-success-block="base/home.html:new_item"

Blocks are regular Django template blocks. E.g.

{% block welcome_block %}<p>some html here</p>{% endblock }

HttpResponse classes (main)

The main response classes you will use are

HxResponse(request[, context, block=None, swap=None, trigger-after-receive=None, trigger_after_settle=None, trigger_after_swap=None])

Creates a TemplateResponse-like object using django-render-block and htmx header functions. Its main purpose is to make it easy to specify - on the server side - what htmx should do with a response.

Automatically gets the block name from HX-Block header, or it can be specified as a kwarg. The format of block should be path/to/template.html:block_name

HxResponse(request, { 'form': form })

Supports optional kwargs

HxResponse(request, { 'form': form, trigger-after-receive='do-this-when-response-is-received'})

HxSuccessResponse(request[, context, block=None, swap=None, trigger-after-receive=None, trigger_after_settle=None, trigger_after_swap=None])

Creating a 'success' HxResponse. The response will use any hx-success-* attributes specified in the request markup.

HxErrorResponse(request[, context, block=None, swap=None, trigger-after-receive=None, trigger_after_settle=None, trigger_after_swap=None])

Creates an 'error' HxResponse. The response will use any hx-error-* attributes specified in the request markup.

HttpResponse classes (extra)

Some extra response classes for when you don't intend to swap some new HTML into the page.

HxDoNothing

A HttpResponse that tells htmx to do nothing

HxDoNothing()

HxRedirect

A HttpResponse that tells htmx to do a client side redirect to the provided URL

HxRedirect(reverse('home'))

HxRefresh

A HttpResponse that tells htmx to refresh the page

HxRefresh()

HxTrigger(trigger_after_receive=None, trigger_after_swap=None, trigger_after_settle=None)

A HttpResponse that tells htmx to trigger an event - and do nothing else. https://htmx.org/headers/hx-trigger/

trigger: the name of the event to trigger. Can also be JSON string, which allows for triggering multiple events and/or passing data for the event

HxTrigger('close-modal')

BlockResponse(block)

Creates a TemplateResponse-like object using django-render-block to render just a block in a template The format of block is template_path/template_name:block_name.

BlockResponse('base/home.html:welcome_block')

okayjack-htmx's People

Contributors

benopotamus avatar

Watchers

 avatar

okayjack-htmx's Issues

Handle PATCH in the same or similar way to POST

Django handles POST requests well. It also accepts PATCH requests, but it doesn't put the data in a request.PATCH attribute. Okayjack has some middleware to populate request.PATCH, but it doesn't handle file uploads (hx-encoding="multipart/form-data").

Ideally, Okayjack would populate request.PATCH in the same (or similar) way as is done for request.POST.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.