Skip to content

Commit

Permalink
Add hook and example for connectedMoveCallback
Browse files Browse the repository at this point in the history
  • Loading branch information
noamr committed Dec 3, 2024
1 parent 7a9b711 commit 4a5aebb
Showing 1 changed file with 72 additions and 3 deletions.
75 changes: 72 additions & 3 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -71672,7 +71672,8 @@ console.log(plasticButton.outerHTML); // will output '<button is="plastic-but
responsibility of conveying button semantics (including the ability to be disabled) might look
something like this:</p>

<pre><code class="js">class TacoButton extends HTMLElement {
<pre id="custom-elements-autonomous-drawbacks-example"><code
class="js">class TacoButton extends HTMLElement {
static observedAttributes = ["disabled"];

constructor() {
Expand Down Expand Up @@ -71985,6 +71986,73 @@ document.body.append(parent);
// CChild connectedCallback: isConnected = false</code></pre>
</div>

<h5>Preserving custom element state when moved</h5>

<!-- NON-NORMATIVE SECTION -->

<p>When manipulating the DOM tree, an element can be <span
data-x="concept-node-move-ext">moved</span> in the tree while connected. This applies to custom
elements as well. By default, the "<code data-x="">disconnectedCallback</code>" and "<code
data-x="">connectedCallback</code>" would be called on the element, one after the other. This is
done to maintain compatibility with existing custom elements that predate the <code
data-x="dom-Node-moveBefore">moveBefore</code> method. This means that by default, custom elements
reset their state as if they were removed and re-inserted. In the example <a
href="#custom-elements-autonomous-drawbacks-example">above</a>, the impact would be that the
observer would be disconnected and re-connected, and the tab index would be reset.</p>

<p>To opt in to a state-preserving behavior while <span
data-x="concept-node-move-ext">moveing</span>, the author can implement a "<code
data-x="">connectedMoveCallback</code>". The existence of this callback, even if empty, would
supercede the default behavior of calling "<code data-x="">disconnectedCallback</code>" and "<code
data-x="">connectedCallback</code>". "<code data-x="">connectedMoveCallback</code>" can also be
an appropriate place to execute logic that depends on the element's ancestors. For example:</p>

<pre><code class="js">class TacoButton extends HTMLElement {
static observedAttributes = ["disabled"];

constructor() {
super();
this._internals = this.attachInternals();
this._internals.role = "button";

this._observer = new MutationObserver(() => {
this._internals.ariaLabel = this.textContent;
});
}

_notifyMain() {
if (this.parentElement.tagName === "MAIN") {
// Execute logic that depends on ancestors.
}
}

connectedCallback() {
this.setAttribute("tabindex", "0");

this._observer.observe(this, {
childList: true,
characterData: true,
subtree: true
});

this._notifyMain();
}

disconnectedCallback() {
this._observer.disconnect();
}

// Implementing this function would avoid resetting the tab index or re-registering the
// mutation observer when this element is moved inside the DOM without being disconnected.
connectedMoveCallback() {
// The parent can change during a state-preserving move.
this._notifyMain();
}
}</code></pre>




<h4 id="custom-elements-core-concepts">Core concepts</h4>

<p>A <dfn export>custom element</dfn> is an element that is <span
Expand Down Expand Up @@ -72415,8 +72483,9 @@ dictionary <dfn dictionary>ElementDefinitionOptions</dfn> {

<li><p>Let <var>lifecycleCallbacks</var> be a map with the keys "<code
data-x="">connectedCallback</code>", "<code data-x="">disconnectedCallback</code>", "<code
data-x="">adoptedCallback</code>", and "<code data-x="">attributeChangedCallback</code>", each
of which belongs to an entry whose value is null.</p>
data-x="">connectedMoveCallback</code>", "<code data-x="">adoptedCallback</code>", and "<code
data-x="">attributeChangedCallback</code>", each of which belongs to an entry whose value is
null.</p>

<li>
<p>For each of the keys <var>callbackName</var> in <var>lifecycleCallbacks</var>, in the
Expand Down

0 comments on commit 4a5aebb

Please sign in to comment.