-
-
Notifications
You must be signed in to change notification settings - Fork 32
proposal: Add hydro-skip directive #122
Description
Background
When HydroComponent is re-rendered, Hydro uses Alpine.morph to update the client-side DOM, including updating Attributes and Children DOM Nodes. However, not all scenarios are suitable for such updates. For example, when a user integrates a third-party component library into the page and needs to update the component state using the method required by that library via the JS API, Hydro's DOM update functionality should skip these components to avoid conflicts.
Proposal Content
It is suggested to add a hydro-skip directive to help Hydro skip updates for certain DOM elements.
Case 1: Completely Skip Updates for a DOM Subtree
<third-party-comp hydro-skip foo="bar" />third-party-comp is a Web Component from a third-party library. By adding hydro-skip to it, Hydro can avoid modifying its attributes and the DOM subtree created by its JS at runtime during the morph phase.
Case 2: Skip Only the Element Itself
<third-party-comp hydro-skip="self" foo="bar">
<div slot="title"> @Model.Title</div>
<div>@Model.Content</div>
</third-party-comp>third-party-comp is a Web Component or JS component from a third-party library. By adding hydro-skip="self" to it, Hydro can avoid modifying its attributes during the morph phase but continue to update its DOM subtree.
Discussion on Alternative Solutions
Can We Use HydroComponent with a Stable Key to Avoid Morph Updates?
HydroComponent does not support Slot, so it cannot handle Case 2.
Pros and Cons Analysis
Pros
Allows developers to use other JS Libraries to enhance the client-side user experience:
<button x-on:click="HighlightTextJSLib.toggle('some-highlight')">Toggle</button>
<highlight-text name="some-highlight" hydro-skip="self"> // highlight-text will add `style` to itself
<div>@Model.Content</div>
</highlight-text>Additionally, developers can maintain part of the UI state on the client side to reduce the number of requests and enhance the user experience. For example, developers can directly use JS to set the open state of a Dialog or the play position of a carousel.
Cons
Once an element is marked with hydro-skip, it will never receive any updates directly from the server.
As an alternative, we can update the component state on the client side via ExecuteJs.
Implementation Plan
I have prepared a rough plan. Adding a small piece of handling logic at line 442 will suffice.
Lines 442 to 447 in 9ff5291
| // set the operation id, disabled state and hydro class that would be lost after morph | |
| to.setAttribute("data-operation-id", from.getAttribute("data-operation-id")); | |
| to.disabled = from.disabled; | |
| if (from.classList.contains('hydro-request')) { | |
| to.classList.add('hydro-request'); |
if (from.getAttribute && from.getAttribute("hydro-skip")) {
const skip = from.getAttribute("hydro-skip");
if (skip === 'self') {
childrenOnly();
counter++;
return;
} else {
skip();
counter++;
return;
}
}