Skip to content

proposal: Add hydro-skip directive #122

@ZeekoZhu

Description

@ZeekoZhu

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.

hydro/src/Scripts/hydro.js

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;
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions