sercrod

*restore

Summary

*restore discards staged edits and restores the staged view back to the last stable state of the host data. It is part of the staged editing flow together with *stage and *apply, and it only makes sense when the host is configured with *stage or n-stage.

Alias:

Basic example

A typical staged form with apply and restore buttons:

<serc-rod id="profile" data='{
  "user": { "name": "Alice", "email": "alice@example.com" }
}'>
  <form *stage="draft">
    <label>
      Name:
      <input *input="draft.user.name">
    </label>
    <label>
      Email:
      <input *input="draft.user.email">
    </label>

    <button type="button" *apply>Save</button>
    <button type="button" *restore>Reset</button>
  </form>
</serc-rod>

Behavior:

Behavior

Key points:

Relationship to *stage and *apply

*restore is one of three core directives that define the staged editing lifecycle:

In other words:

Evaluation timing

*restore is processed during element rendering after host-level *if and other structural checks:

Execution model

Conceptually, for each element with *restore or n-restore:

  1. During render:

    • Sercrod detects that work has *restore or n-restore.

    • It creates el = work.cloneNode(true).

    • It registers:

      • el.addEventListener("click", handler),

      where handler is closed over the host instance.

    • It appends el to the parent.

    • It returns from the directive branch for this element.

  2. When the user clicks the element:

    • The handler checks if the host has *stage or n-stage.

      • If not, it returns without changes.
    • It calculates the base:

      • base = this._applied ?? this._data.
    • It clones base into _stage:

      • Preferentially via structuredClone.
      • Falls back to JSON.parse(JSON.stringify(base)) if needed.
    • It calls this.update() to re-render the host.

  3. On re-render:

    • Because _stage is now a fresh clone of the base state, the entire staged view is reset to that state.

Variable creation and scope layering

*restore does not introduce or modify template-level variables:

From the perspective of expressions:

Parent access

*restore does not provide a dedicated handle to parent scopes on its own:

The main effect of *restore is to redefine the contents of _stage, which then becomes the source for subsequent renders.

Use with conditionals and loops

You can combine *restore with conditionals and loops on the same or surrounding elements, as long as they do not conflict structurally:

Best practices

Additional examples

Simple “revert to original data” without any prior apply:

<serc-rod id="simple" data='{"counter": 0}' *stage="draft">
  <p>Value: <span *print="draft.counter"></span></p>

  <button type="button" *restore>Reset</button>
  <button type="button" @click="draft.counter++">Increment</button>
</serc-rod>

Staged form with multiple commits:

<serc-rod id="multi" data='{"value": "initial"}' *stage="draft">
  <input *input="draft.value">

  <button type="button" *apply>Apply</button>
  <button type="button" *restore>Restore</button>
</serc-rod>

Notes