Tuesday, May 13, 2025
HomeJavaScriptConditionally Stopping HX-Increase In HTMX Utilizing An Extension

Conditionally Stopping HX-Increase In HTMX Utilizing An Extension


In an HTMX software, the built-in hx-boost attribute tells HTMX to intercept all kind and anchor interactions and “AJAX’ify” them. That’s, forestall the default browser habits and re-implement it utilizing AJAX and the Historical past API as a way to side-step a full page-load. It is a neat function; however, it does not have any hooks (that I can discover) to conditionally forestall hx-boost from performing on a given hyperlink. Such a hook could be needed when integrating content material that comes out of a content material administration system (CMS). To attempt to add such a hook, I’ve created my first HTMX extension, prevent-boost, that may conditionally forestall boosting primarily based on RegEx patterns and / or filter callbacks.

Contemplate the next ColdFusion web page that is a part of an HTMX web site:

<cfoutput>

	<h1>
		About
	</h1>

	<!---
		Think about that that is popping out of a content material administration system and we do not have
		direct entry to the HTML. As such, we won't apply hx-boost or hx-disabled to the
		markup instantly. As a substitute, we've got to depend on our extension to stop boosting.
	--->
	<part data-source="content material administration system">
		<p>
			Try my <a href="https://www.bennadel.com/weblog/demo.cfm">Demo App</a>.
		</p>
	</part>

</cfoutput>

For this exploration, the entire CFML is hard-coded; however, think about that the above <part> factor is popping out of a CMS. And, whereas the general HTMX web site is utilizing hx-boost, there could also be content material coming from the CMS that should not be boosted as a result of it hyperlinks to a non-compatible web page. On this case, we do not need demo.cfm to be boosted.

Usually, we might simply add hx-disable or hx-boost="false" to the demo hyperlink. However, once more, we’re pretending that we do not have direct entry to this markup. As such, we’ve got to implement the “disabling” after the very fact.

To do that, we are able to use an HTMX extension to hook into the htmx:beforeProcessNode occasion. That is the occasion that will get fired proper earlier than HTMX examines a node to see if it must initialize any information or bind any triggers. We are able to use this occasion, inside our extension, to conditionally inject the aforementioned hx-disable and hx-boost="false" attributes.

Apart: We’d solely must inject one in all these attributes. However, I am injecting each for enjoyable; and since I am utilizing the hx-boost attribute extra for documentation than for performance (see the code beneath).

This interception is finished through the extension’s onEvent() handler. Each HTMX occasion (that may be prolonged) is handed to this handler, giving our extension a possibility to enhance varied management flows throughout the software’s habits.

On this case, we will search for particular htmx:beforeProcessNode occasions&mdahs;these which might be working on anchor tags. For every inspected anchor tag, we will extract the href property and evaluate it to a given set of RegEx patterns or filters. And, if any filter returns false, we will inject the hx-disable and hx-boost attributes into mentioned anchor tag.

First, let’s take a look at an abbreviated model of the structure template the place the script tags are being put in to see how this HTMX extension will be configured:

<cfoutput>

	<!doctype html>
	<html lang="en">
	<head>
		<!--- ... truncated ... --->

		<script kind="textual content/javascript" src="https://www.bennadel.com/shared/htmx-2.0.4.js"></script>
		<script kind="textual content/javascript" src="./prevent-boost.js"></script>
		<script kind="textual content/javascript">

			// DO NOT BOOST on "/demo.cfm" hyperlinks.
			HxPreventBoost.addPattern( //demo.cfmb/i );

		</script>
	</head>
	<physique
		hx-boost="true"
		hx-sync="this:exchange"
		hx-ext="prevent-boost">

		<!--- ... truncated ... --->

	</physique>
	</html>

</cfoutput>

On this code, there are a number of issues to note:

  1. I am together with the hx-boost attribute on the physique to spice up your entire web site.

  2. I am together with the hx-ext="prevent-boost" attribute on the physique to inform HTMX that I wish to apply my extension to your entire physique content material.

  3. I am together with my extension script tag after I embrace the HTMX framework.

  4. My extension exposes a world HxPreventBoost variable, which exposes a option to configure the extension habits. And, proper after I embrace my script tag, I am including a RegEx sample to match in opposition to the /demo.cfm hyperlink.

We are able to see that this extension is working by trying on the community exercise as we click on across the web site. For many hyperlinks, we’ll see that solely the highest degree web page is requested, bypassing any full-page load. Nevertheless, after we click on on the demo.cfm hyperlink, we are able to see that every one the static property are loaded. It is because the boosting habits was prevented and full-page load was executed:

Network activity showing that the demo link caused a full-page load.

As you may see, most hyperlinks solely load the primary content material because of hx-boost. However, the demo.cfm hyperlink, which is intercepted by our extension, causes a full-page load, together with the entire linked static property.

This is my implementation of the extension:

window.HxPreventBoost = (() => {

	// Filter features are given the node and href and might return an express false to
	// disable boosting on the given node.
	var filters = [];

	htmx.defineExtension(
		"prevent-boost",
		{
			onEvent: handleHtmxEvent
		}
	);

	// Return the general public API.
	return {
		addFilter,
		addPattern
	};

	// ---
	// PUBLIC METHODS.
	// ---

	/**
	* I add the given filter to the node pre-processing logic. If a filter returns an
	* express (false), hx-boost will probably be disabled on the given node.
	*/
	operate addFilter( filter ) {

		filters.push( filter );

	}


	/**
	* I add the given common expression sample to the node pre-processing logic. If a
	* sample matches in opposition to a given HREF property, hx-boost will probably be disabled on the
	* given node.
	* 
	* Notice: the HREF worth used within the sample match is the `.href` property worth. If you happen to
	* want to check in opposition to the unique href attribute, use a filter and entry the
	* attribute utilizing the passed-in node.
	*/
	operate addPattern( patternText, patternFlags = "i" ) {

		var sample = ( patternText instanceof RegExp )
			? patternText
			: new RegExp( patternText, patternFlags )
		;

		addFilter( ( node, href ) => ( sample.check( href ) === false ) );

	}

	// ---
	// PRIVATE METHODS.
	// ---

	/**
	* I present interception logic for the HTMX occasions.
	*/
	operate handleHtmxEvent( title, occasion ) {

		// There is not any method (that I can discover) to carry out a just-in-time cancellation of the
		// hx-boost operation (with out truly canceling the default browser habits as
		// properly). As such, we will forestall boosting on the different finish of the life-
		// cycle, when HTMX is initializing the HTML content material. As HTMX traverses the brand new
		// DOM fragments, on the lookout for nodes to course of, we will conditionally add
		// the hx-boost/hx-disable attributes to nodes that we wish to skip. This may
		// forestall HTMX from taking additional motion.
		if ( title !== "htmx:beforeProcessNode" ) {

			return;

		}

		var node = occasion.element.elt;
 
		// At present, this extension solely handles anchor tags.
		if ( node.tagName !== "A" ) {

			return;

		}

		for ( var filter of filters ) {

			if ( filter( node, node.href ) === false ) {

				return preventBoost( node );

			}

		}

	}


	/**
	* I apply attributes to the node in order that HTMX will ignore interactions.
	*/
	operate preventBoost( node ) {

		node.setAttribute( "hx-boost", "false" );
		node.setAttribute( "hx-disable", "disabled by prevent-boost extension" );

	}

})();

And, if we have a look at the HTML of the rendered web page, we are able to see that the hx-boost and hx-disabled attributes had been dynamically injected by my extension:

Screenshot of the live HTML showing that hx-boost and hx-disabled have been dynamically injected on the demo link.

I do know that utilizing hx-boost is a little bit of controversial subject. It undoubtedly makes some issues simpler and a few issues tougher. Coming from a SPA (single-page software) world, this seems like pure stepping stone. And, in the meanwhile, I am glad that I can embrace hx-boost and nonetheless have methods to disable it the place and after I must, even with out direct entry to the HTML content material.

Need to use code from this put up?
Try the license.


https://bennadel.com/4784

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments