Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/phpcsfixer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php-versions: ['8.1', '8.2', '8.4']
php-versions: ['8.2', '8.5']

steps:
- name: Checkout
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/phpstan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php-versions: ['8.1', '8.4']
php-versions: ['8.2', '8.4']

steps:
- name: Checkout
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/phpunit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
if: "!contains(github.event.head_commit.message, '[ci skip]')"
strategy:
matrix:
php-versions: ['8.1', '8.2', '8.3', '8.4', '8.5']
php-versions: ['8.2', '8.3', '8.4', '8.5']

steps:
- name: Free Disk Space (Ubuntu)
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# CodeIgniter HTMX

A set of methods for `IncomingRequest`, `Response` and `RedirectResponse` classes to help you work with [htmx](https://htmx.org) fluently in CodeIgniter 4 framework.
A set of methods for `IncomingRequest`, `Response` and `RedirectResponse` classes to help you work with [htmx](https://four.htmx.org/) fluently in CodeIgniter 4 framework.

It also provides some additional help with **handling errors** and **Debug Toolbar** in development mode as well as support for **view fragments**.

The `develop` branch targets the HTMX 4 request/response model and development event lifecycle.

[![PHPUnit](https://github.com/michalsn/codeigniter-htmx/actions/workflows/phpunit.yml/badge.svg)](https://github.com/michalsn/codeigniter-htmx/actions/workflows/phpunit.yml)
[![PHPStan](https://github.com/michalsn/codeigniter-htmx/actions/workflows/phpstan.yml/badge.svg)](https://github.com/michalsn/codeigniter-htmx/actions/workflows/phpstan.yml)
[![Deptrac](https://github.com/michalsn/codeigniter-htmx/actions/workflows/deptrac.yml/badge.svg)](https://github.com/michalsn/codeigniter-htmx/actions/workflows/deptrac.yml)
Expand Down
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
],
"homepage": "https://github.com/michalsn/codeigniter-htmx",
"require": {
"php": "^8.0"
"php": "^8.2"
},
"require-dev": {
"codeigniter4/devkit": "^1.0",
"codeigniter4/framework": "^4.3"
"codeigniter4/devkit": "^1.3",
"codeigniter4/framework": "^4.7"
},
"minimum-stability": "dev",
"prefer-stable": true,
Expand Down
7 changes: 3 additions & 4 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ In the `production` environment these decorators are ignored by design. So this
Specifies whether the HTMX request URL should be stored in the session, for use with the `previous_url()` helper function.
For more information, see the [user guide](https://codeigniter.com/user_guide/helpers/url_helper.html#previous_url).

Basically, if you use HTMX extensively, including for navigating your site, you will probably want to leave it as `true`,
and in cases where storing the request is not desirable, even if it uses HTMX, you can use custom header, to indicate the
AJAX call or [ajax-header](https://github.com/bigskysoftware/htmx-extensions/blob/main/src/ajax-header/README.md) extension,
which will add the necessary headers automatically. URLs from AJAX requests are always excluded from session storage.
Basically, if you use HTMX extensively, including for navigating your site, you will probably want to leave it as `true`.
If storing the request is not desirable, mark it as a traditional AJAX request or use a custom header in your application flow.
URLs from AJAX requests are always excluded from session storage.
2 changes: 1 addition & 1 deletion docs/debug_toolbar.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Debug Toolbar

As long as you **don't use** the [head-support](https://htmx.org/extensions/head-support/) extension,
As long as you **don't use** the [head-support](https://four.htmx.org/docs/extensions/head-support) extension,
the Debug Toolbar should work out of the box. It will be updated after every request, so please remember
it will only display the latest information. If you want to see what happened in earlier request,
use the `History` tab in the Toolbar.
Expand Down
22 changes: 21 additions & 1 deletion docs/error_handling.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# Error handling

By default, when an HTTP error response occurs, htmx is not displaying the error. This library changes it so that in the development mode, errors are displayed in a modal window.
HTMX 4 handles error responses through its response handling rules, using `hx-status:*` attributes and `htmx.config.noSwap`.

In development mode, when `errorModalDecorator` is enabled, this library overrides that default browser-side behavior for failed HTMX requests.

Instead of allowing HTMX to continue with its normal response handling, the raw response is displayed in a modal window and the normal HTMX swap is skipped.

This makes it easier to inspect exception pages, validation output, and malformed HTML returned during development, without changing the actual HTTP status code.

HTML error pages are shown in a sandboxed preview iframe, with a source view available for inspecting the raw response. JSON and plain-text responses are shown directly as source.

If you want to use HTMX's native error handling rules in development instead, disable `errorModalDecorator` in the config.

When the decorator is disabled, you can configure HTMX directly, for example:

```html
<script>
htmx.config.noSwap = [204, 304, '4xx', '5xx'];
</script>
```

You can also use `hx-status:*` attributes to define per-status error targets in your application.

This feature can be disabled in the [Config](configuration.md) file.
8 changes: 5 additions & 3 deletions docs/html_formatter.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ We should edit the `app/Config/Format.php` file to include the necessary changes

php spark htmx:publish

Since content negotiation will be triggered for any format other than `json` or `xml`, we have two options:
With HTMX 4, requests already send `Accept: text/html`, so in the most common HTMX case no extra client-side configuration is needed.

1. Set the custom headers for every request via HTML tag
If you want to use the formatter outside HTMX requests, you still have two options:

1. Set the custom headers for a request explicitly
```html
hx-headers='{"Accept":"text/html"}'
```
Expand All @@ -28,7 +30,7 @@ Since content negotiation will be triggered for any format other than `json` or

### Example

This is an sample of using HTML formatter:
This is a sample of using HTML formatter:

```php
<?php
Expand Down
160 changes: 160 additions & 0 deletions docs/htmx_4_migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# HTMX 4 migration

This package now follows the HTMX 4 request/response model.

The most important HTMX 4 changes for this package are:

- Requests use `fetch()` instead of `XMLHttpRequest`.
- Browser event names use the `htmx:phase:action` format.
- `HX-Source` replaces `HX-Trigger`.
- `HX-Request-Type` is available with `partial` and `full` values.
- `HX-Target` now uses the `tag#id` identifier format.
- `HX-Prompt` and `HX-Trigger-Name` are no longer sent by HTMX 4 clients.
- Error response handling is configured through `hx-status:*` and `htmx.config.noSwap`.

## Quick start

If you want to preserve the most common HTMX 2 defaults while you migrate your application, add:

```html
<script>
htmx.config.implicitInheritance = true;
htmx.config.noSwap = [204, 304, '4xx', '5xx'];
</script>
```

This is only a transition aid. For a native HTMX 4 setup, prefer explicit `:inherited` attributes and keep the default `noSwap` behavior unless your application needs something else.

## IncomingRequest changes

Use the new methods when working with HTMX 4 requests:

```php
$this->request->getSource();
$this->request->getRequestType();
$this->request->isPartial();
$this->request->isFull();
```

## Response behavior

HTMX 4 still supports the response headers used by this package, including:

- `HX-Location`
- `HX-Push-Url`
- `HX-Redirect`
- `HX-Refresh`
- `HX-Replace-Url`
- `HX-Retarget`
- `HX-Reswap`
- `HX-Reselect`
- `HX-Trigger`

## Error responses

If you want to avoid swapping `4xx` and `5xx` responses, configure:

```html
<script>
htmx.config.noSwap = [204, 304, '4xx', '5xx'];
</script>
```

You can also enable HTMX 2 compatibility mode in the browser:

```html
<script src="/path/to/htmx.js"></script>
<script src="/path/to/ext/htmx-2-compat.js"></script>
```

## Attribute inheritance

HTMX 4 uses explicit inheritance by default.

If your markup relied on inherited attributes such as `hx-target`, `hx-boost`, or `hx-confirm`, update the attributes to use the `:inherited` modifier:

```html
<div hx-confirm:inherited="Are you sure?">
<button hx-delete="/item/1">Delete</button>
</div>
```

If you need the old behavior:

```html
<script>
htmx.config.implicitInheritance = true;
</script>
```

For larger migrations, the HTMX 2 compatibility extension can be a more convenient temporary bridge than enabling `implicitInheritance` globally.

## Request markup changes

HTMX 4 also changes a few client-side attributes that may affect applications using this package:

- `hx-delete` no longer includes enclosing form values automatically. Use `hx-include="closest form"` when needed.
- In HTMX 2, `hx-disable` prevented HTMX processing. In HTMX 4 that behavior moved to `hx-ignore`, while `hx-disabled-elt` was renamed to `hx-disable`.
- `hx-request` was replaced by `hx-config`.
- `hx-prompt` was removed. Use `hx-confirm` with JavaScript instead.
- `hx-ext` was removed. Extensions now register through standard events, so load the extension script directly and use its attributes where needed.
- `hx-history` and `hx-history-elt` were removed.
- `data-hx-*` attributes are no longer recognized automatically unless you configure `htmx.config.prefix`.

## History behavior

HTMX 4 no longer stores page snapshots in browser storage.

When the user navigates through history, HTMX issues a new full-page request instead. The `HX-History-Restore-Request` header is still available, so this package continues to expose `isHistoryRestoreRequest()`.

If you want hard browser reloads on history navigation instead of HTMX restoration, use:

```html
<script>
htmx.config.history = 'reload';
</script>
```

## Out-of-band swap order

In HTMX 4, the main swap happens before `hx-swap-oob` content.

If your UI depends on out-of-band fragments being processed first, review the markup and make each swap independent.

## Timeouts

HTMX 4 sets a 60-second request timeout by default:

```html
<script>
htmx.config.defaultTimeout = 60000;
</script>
```

If your application expects no timeout, set it back to `0`.

## Extensions

Extensions are now loaded by including their scripts directly.

```html
<script src="/path/to/htmx.js"></script>
<script src="/path/to/ext/sse.js"></script>
```

You can optionally restrict which extensions may load with `htmx.config.extensions`.

## Caching

If your application returns different HTML for full and partial HTMX requests, configure caching carefully and consider sending:

```http
Vary: HX-Request-Type
```

If responses also depend on the source or target element, extend the `Vary` header accordingly.

## References

- [HTMX 4 migration guide](https://four.htmx.org/docs/get-started/migration)
- [HTMX 4 reference](https://four.htmx.org/reference/)
Loading
Loading