HTMX hx-post Attribute

The hx-post attribute sends a POST request to the server when an element is triggered. You use POST when you want to send data to the server — such as a new comment, a form submission, or a record to save. The server processes the data and returns an HTML fragment, which HTMX places into the page.

GET vs POST: A Quick Reminder

MethodPurposeSends DataCommon Use
GETFetch dataOnly in URL (query string)Loading a page, searching
POSTSend dataIn the request body (hidden)Creating, submitting, saving

Basic Syntax

<button hx-post="/save-item" hx-target="#status">
  Save Item
</button>

<div id="status"></div>

When the user clicks "Save Item," HTMX sends a POST request to /save-item. The server processes the request and returns an HTML fragment — for example, a success message — which HTMX places into #status.

Posting Form Data

The most common use of hx-post is on a form. When you put hx-post on a <form> element, HTMX collects all the input values and sends them as the POST body automatically.

<form hx-post="/submit-comment" hx-target="#comment-list" hx-swap="beforeend">
  <input type="text" name="author" placeholder="Your name">
  <textarea name="body" placeholder="Write your comment..."></textarea>
  <button type="submit">Post Comment</button>
</form>

<ul id="comment-list">
  <li>First comment already here.</li>
</ul>
  Diagram:

  User fills in name + comment, clicks "Post Comment"
          |
          v
  HTMX collects form data:
    author = "Alice"
    body   = "Great article!"
          |
          v
  POST /submit-comment  (data sent in request body)
          |
          v
  Server saves comment, returns:
    <li>Alice: Great article!</li>
          |
          v
  HTMX appends the <li> to #comment-list
          |
          v
  Page shows new comment at the bottom of the list — no reload

hx-post on a Button Inside a Form

When a button with hx-post sits inside a <form>, HTMX automatically includes all sibling input values in the POST body. This means you can trigger the submission from the button without putting hx-post on the form tag itself.

<form>
  <input type="text" name="title" placeholder="Task title">
  <button hx-post="/tasks" hx-target="#task-list" hx-swap="beforeend">
    Add Task
  </button>
</form>

<ul id="task-list"></ul>

Including Extra Data With hx-vals

You can attach extra data to any POST request using the hx-vals attribute. This is useful when you need to send additional context that is not in a form input.

<button
  hx-post="/like"
  hx-vals='{"post_id": 42}'
  hx-target="#like-count">
  Like
</button>

HTMX sends post_id=42 along with the POST request, even though there is no visible input field for it.

Real Example: Newsletter Sign-Up

<form hx-post="/subscribe" hx-target="#signup-message" hx-swap="outerHTML">
  <input type="email" name="email" placeholder="Enter your email" required>
  <button type="submit">Subscribe</button>
</form>

<div id="signup-message"></div>

Server response on success:

<div id="signup-message">
  <p>You are subscribed! Check your inbox.</p>
</div>

Because hx-swap="outerHTML" replaces the entire target element (including the id), HTMX swaps out the old #signup-message div with the new one from the server — which now contains the confirmation text.

Server-Side Handling

Your server receives the POST data in the request body. Here is how each common framework reads it:

Flask (Python)

@app.route('/submit-comment', methods=['POST'])
def submit_comment():
    author = request.form.get('author')
    body   = request.form.get('body')
    # save to database...
    return f'<li>{author}: {body}</li>'

Express (Node.js)

app.post('/submit-comment', (req, res) => {
  const { author, body } = req.body;
  // save to database...
  res.send(`<li>${author}: ${body}</li>`);
});

Security: CSRF Protection

POST requests that modify server data require CSRF (Cross-Site Request Forgery) protection on most frameworks. To include a CSRF token with your HTMX POST, add the token as a hidden input inside your form:

<form hx-post="/save" hx-target="#result">
  <input type="hidden" name="csrf_token" value="your-token-here">
  <input type="text" name="title" placeholder="Title">
  <button type="submit">Save</button>
</form>

Alternatively, you can add the CSRF token to every HTMX request globally using a meta tag and a small JavaScript snippet, which the Security topic covers in detail.

Key Takeaway

The hx-post attribute sends data to the server when a user submits a form or clicks a button. HTMX automatically collects form input values and includes them in the POST body. The server saves the data and returns an HTML fragment confirming what happened. The page updates without a reload. Always include CSRF protection for any POST route that modifies server state.

Leave a Comment

Your email address will not be published. Required fields are marked *