0.1.7 • Published 7 months ago

htmx-serverless v0.1.7

Weekly downloads
-
License
ISC
Repository
github
Last release
7 months ago

HTMX Serverless Client States npm npm PRs Welcome

To use HTMX you require a back-end server to handle the XHR requests and responses. In some cases it is nice to have only a client side interaction to handle client states, without network requests.

This extension uses the HTMX built-in Events to intercept some XHR requests before they fire and define response texts on the client side. No need for mock or "fake" server scripts. It is HTMX without a server (sort of).

Usage

In HTML head

<!-- htmx  -->
<script src="https://unpkg.com/htmx.org"></script>
<!-- serverless extension -->
<script src="https://unpkg.com/htmx-serverless"></script>

Then use the window.htmxServerless global to set custom handlers and responses.

// Requests to "/handler1" are replaced with "<div>Custom HTML</div>"
htmxServerless.handlers.set('/handler1', '<div>Custom HTML</div>');

// Requests to "/handler2" are managed via a function
htmxServerless.handlers.set('/handler2', function(text, params, xhr){
    console.log(this, text, params, xhr);
    return "<p>Okay!</p>";
});

// Directly within the hx-{request} attribute, return value of myFunc is the replacement
<button hx-get="js:myFunc" hx-swap="outerHTML" hx-ext="serverless">
    Click to replace via myFunc!
</button>

In custom bundles

import htmx from "htmx.org";
import htmxServerless from "htmx-serverless";

// Initialize on your local htmx
htmxServerless.init(htmx);

Examples

Handler as a string

Assume we have a button with the serverless hx-ext sattribute, which triggers a request to the path "/clicked":

<button hx-get="/clicked" hx-swap="outerHTML" hx-ext="serverless">
    Click to replace!
</button>

To define a serverless client side response to "/clicked" in the handlers Map():

htmxServerless.handlers.set('/clicked', 
    `<button hx-get="/clicked" hx-swap="outerHTML" hx-ext="serverless">
        Hey, you clicked me!
    </button>`
);

The button is then replaced with the HTML defined without triggering a request to the server. It's that simple.

Try this example here.

Handler as a Function set excplicitly

Tha handler function is a great tool for more complex conditional logic, like it would happen on the server side. Let's make a simple click based number increment handler:

<button hx-get="/count" 
        hx-target="next .counter" 
        hx-trigger="load, click" 
        hx-vals='js:{myVal: i++}' 
        hx-ext="serverless">Click to Increment</button>
<span class="counter"></span>
   

The handler only needs to print the text as "i" is incremented by hx-vals automatically:

let i = 0;
htmxServerless.handlers.set('/count', function(text, params, xhr){
    let status = params?.myVal < 10 ? "smaller or equals to" : "bigger than";
    return `Value of "myVal" is: ${params?.myVal}, it is ${status} 10.`;
});

Try this example here.

Output:

Alt text

Handler as a Function via js:myFunc

You can set the handler function implicitly in the hx-{get,post etc..} attribute via the js:myFunc syntax:

<button hx-get="js:counter" 
        hx-target="next .counter" 
        hx-trigger="load, click" 
        hx-vals='js:{myVal: i++}' 
        hx-ext="serverless">Click to Increment</button>
<span class="counter"></span>
   

The handler function accepts the same arguments as before:

let i = 0;
function counter(text, params, xhr){
    let status = params?.myVal < 10 ? "smaller or equals to" : "bigger than";
    return `Value of "myVal" is: ${params?.myVal}, it is ${status} 10.`;
}

Try this example here.

Handler function

The handler function accepts 3 parameters (4 including "this") and returns a string:

  • this => The target element
  • ext => The replacement text (empty)
  • params => The GET/POST or xhr-vals arguments
  • xhr => The current request
/**
 * The handler function
 * 
 * @param this:Element The target element
 * @param text:string The replacement text (empty)
 * @param params:Object The GET/POST or xhr-vals arguments
 * @param xhr:XMLHttpRequest The current request
 * 
 * @returns string
 */ 
function handler(text, params, xhr){
    console.log(this, text, params, xhr);
    return 'Hi!';
}

How does it work?

It is really simple:

  • The XHR request will not be sent, the .send() method is overridden for the intercepted request
  • The XHR loadstart, load and loadend events are dispatched instead, as if the request was finished "successfully"
  • Only requests added to the htmxServerless.handlers Map are intercepted
  • Requests are intercepted based on the request path, request arguments does not matter

What else?

Nothing actually. This is only a baseline solution, but it works. There are no fancy features, as htmx is oath to be a small but effective library. With some creativity, you could make this more convenient, I leave it up to you :)

0.1.7

7 months ago

0.1.6

7 months ago

0.1.5

7 months ago

0.1.4

7 months ago

0.1.3

7 months ago

0.1.2

7 months ago

0.1.1

7 months ago

0.1.0

7 months ago