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
8 changes: 4 additions & 4 deletions src/htmx.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -536,8 +536,8 @@ export interface HtmxEventMap {

export type HtmxEvent<K extends keyof HtmxEventMap> = CustomEvent<HtmxEventMap[K]>;

/** Context object accepted by `htmx.ajax()` */
export interface HtmxAjaxContext {
/** Options accepted by `htmx.ajax()` */
export interface HtmxAjaxOptions {
/** Element to use as the request source (for headers, inheritance, etc.) */
source?: Element | string;
/** Event that triggered the request */
Expand Down Expand Up @@ -572,12 +572,12 @@ export interface Htmx {
* Returns a Promise that resolves after the response has been swapped into the DOM.
* @param verb - HTTP method (GET, POST, PUT, PATCH, DELETE)
* @param path - URL to request
* @param context - Swap target element, CSS selector, or full context object
* @param options - Swap target element, CSS selector, or full request context object
* @example
* htmx.ajax('GET', '/items', '#list')
* htmx.ajax('POST', '/save', { target: '#result', swap: 'outerHTML' })
*/
ajax(verb: string, path: string, context?: Element | string | HtmxAjaxContext): Promise<void>;
ajax(verb: string, path: string, options?: Element | string | HtmxAjaxOptions): Promise<void>;
/**
* Find the first element matching `selector` in the document.
*/
Expand Down
26 changes: 13 additions & 13 deletions src/htmx.js
Original file line number Diff line number Diff line change
Expand Up @@ -1579,36 +1579,36 @@ var htmx = (() => {
let result = !detail.cancelled && target.dispatchEvent(evt);
return result
}
ajax(verb, path, context) {
// Normalize context to object
if (!context || context instanceof Element || typeof context === 'string') {
context = {target: context};
ajax(verb, path, options) {
// Normalize options to object
if (!options || options instanceof Element || typeof options === 'string') {
options = {target: options};
}

let sourceElt = typeof context.source === 'string' ?
document.querySelector(context.source) : context.source;
let sourceElt = typeof options.source === 'string' ?
document.querySelector(options.source) : options.source;

// If source selector was provided but didn't match, reject
if (typeof context.source === 'string' && !sourceElt) {
if (typeof options.source === 'string' && !sourceElt) {
return Promise.reject(new Error('Source not found'));
}

// Resolve explicit target if provided; otherwise __createRequestContext
// will resolve from hx-target on the source element
if (context.target) {
let target = this.__resolveTarget(document.body, context.target);
if (options.target) {
let target = this.__resolveTarget(document.body, options.target);
if (!target) {
return Promise.reject(new Error('Target not found'));
}
sourceElt ||= target;
}
sourceElt ||= document.body;

let ctx = this.__createRequestContext(sourceElt, context.event || {});
Object.assign(ctx, context);
if (context.target) ctx.target = this.__resolveTarget(document.body, context.target);
let ctx = this.__createRequestContext(sourceElt, options.event || {});
Object.assign(ctx, options);
if (options.target) ctx.target = this.__resolveTarget(document.body, options.target);
Object.assign(ctx.request, {action: path, method: verb.toUpperCase()});
if (context.headers) Object.assign(ctx.request.headers, context.headers);
if (options.headers) Object.assign(ctx.request.headers, options.headers);

return this.__handleTriggerEvent(ctx);
}
Expand Down
4 changes: 2 additions & 2 deletions test/tests/unit/ajax.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ describe('ajax() unit Tests', function() {
assert.equal(div.innerHTML, 'content!');
});

it('ajax works with no context (defaults to body)', async function() {
it('ajax works with no options (defaults to body)', async function() {
this.skip() // We can't test this as it will replace the body and nuke the test UI lol
return;
mockResponse('GET', '/test', '<div id="ajax-result">body content</div>');
Expand Down Expand Up @@ -235,7 +235,7 @@ describe('ajax() unit Tests', function() {
assert.equal(div.innerHTML, 'deleted!');
});

it('ajax with event context', async function() {
it('ajax with event option', async function() {
mockResponse('POST', '/test', 'clicked!');
createProcessedHTML('<button id="btn">Click</button><div id="result"></div>');
const div = find('#result');
Expand Down
2 changes: 1 addition & 1 deletion www/src/content/docs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ Internally-dispatched events route to the console as follows:

This restores the htmx 2.x convention: if you want an internal failure path to show up in the console, fire an event with `detail.error` (or `detail.warn`); no per-site `console.error` needed.

#### Request context
#### Request Context in Events

All events provide a consistent `ctx` object with request/response information.

Expand Down
8 changes: 4 additions & 4 deletions www/src/content/reference/05-methods/01-htmx-ajax.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ htmx swaps the response into `#messages` and resolves the promise after the requ
```javascript
htmx.ajax(method, url)
htmx.ajax(method, url, target)
htmx.ajax(method, url, context)
htmx.ajax(method, url, options)
```

Pass a selector or element as the target:
Expand All @@ -31,7 +31,7 @@ await htmx.ajax(
)
```

Use a context object to configure the request and swap:
Use an options object to configure the request and swap:

```javascript
await htmx.ajax('POST', '/messages', {
Expand Down Expand Up @@ -73,9 +73,9 @@ await htmx.ajax('GET', '/messages', '#messages')

An unmatched target selector rejects the returned promise.

### `context`
### `options`

Use a context object for more control:
Use an options object for more control. It accepts [request context](/docs#request-context) fields:

```javascript
await htmx.ajax('POST', '/messages', {
Expand Down
Loading