sercrod

*fetch

Summary

*fetch loads JSON from a URL and writes it into Sercrod host data. The JSON response can either replace the entire root data object or be merged into a specific property path. *fetch has an alias n-fetch.

On a Sercrod host element (<serc-rod>), *fetch is typically used for initial data loading. On normal elements (such as <button> or <div>), it can be used for explicit reload buttons or one-time auto fetches.

Key points:

Basic example

Initial data load into a host:

<serc-rod id="app" *fetch="/api/items.json:items">
  <h1>Items</h1>
  <ul *each="item of items">
    <li *print="item.name"></li>
  </ul>
</serc-rod>

Behavior:

URL spec format

The *fetch attribute value is interpreted as a simple string in the following format:

Parsing rules:

Important implications:

Behavior

Core behavior:

Data writing rules:

Update:

Errors:

Host vs normal elements

*fetch behaves differently depending on whether it is placed on the Sercrod host or on a normal element.

  1. On the Sercrod host (<serc-rod>):

    • Handled inside connectedCallback.

    • Sequence:

      • The host parses data.

      • If the parent host is currently loading (for example from its own *fetch), the child host waits.

      • If the host has *fetch or n-fetch:

        • this._loading is set to true.
        • The spec is read from the attribute.
        • Warnings are temporarily suppressed for the duration of _do_load.
        • _do_load(spec) is called.
      • On success:

        • Data is updated according to the rules above.
        • this._loading is set to false.
        • requestAnimationFrame(() => this.update()) is called.
      • If the host does not have *fetch:

        • The host calls update() normally.

    Implications:

    • When *fetch is on the host, the first Sercrod render happens after the fetch completes.
    • Child hosts can check parent._loading and delay their own initialization until the parent is done.
  2. On normal elements (button, link, div, etc.):

    • Handled inside the element rendering pipeline.
    • Sercrod clones the element, sets up *fetch behavior, appends the clone, and renders its children.

    Clickable vs non-clickable:

    • Clickable elements:

      • Recognized as clickable if:

        • tagName is BUTTON, or
        • tagName is A without download, or
        • tagName is INPUT with type in button, submit, reset, image.
      • For clickable elements:

        • No automatic fetch is performed.
        • A click listener is attached, calling _do_load(spec) on each click.
    • Non-clickable elements:

      • For non-clickable tags (such as div, section, span, etc.):

        • *fetch is auto-triggered once after initial render.

        • A “once key” is derived from the spec to prevent repeated automatic fetches.

        • If this once key has not been seen before, Sercrod:

          • Records it in an internal set for this host.
          • Schedules _do_load(spec) with requestAnimationFrame.

    Children:

    • In both cases, after cloning and setting up *fetch, Sercrod renders the element’s children normally.
    • Child directives (*print, *if, *each, etc.) can immediately read from existing data.
    • After the fetch completes, the host rerender updates those children with the new data.

Once-key and the ts parameter

For non-clickable elements, *fetch auto-runs “at most once per URL spec” by using an internal once key.

The once key is derived as follows:

Implications:

Events

*fetch communicates its progress via DOM events on the host:

Notes:

*fetch does not set or use $pending, $error, $download, or $upload in data. Those state helpers are used by *api and *post, not by *fetch.

Interaction with *api, *post, and *into

*fetch, *post, and *api are all “request” directives that write into host data, but they differ in capabilities:

Ordering and combinations:

Recommendations:

*into is reserved for *api and is not used by *fetch.

Use with conditionals and loops

*fetch is not a structural directive by itself, so it composes with structural directives as long as they are applied at different levels.

Typical patterns:

Because *post, *fetch, and *api all treat HTTP communication as “JSON in, JSON out” and share the same state flags, it is natural to standardize server-side handlers around this contract.

Recommended approach on the server:

Benefits for server-side code:

Position in Sercrod’s design:

Best practices

Additional examples

Host-level full replacement:

<serc-rod id="profile" *fetch="/api/profile.json">
  <h1 *print="name"></h1>
  <p *print="email"></p>
</serc-rod>

Host-level partial update:

<serc-rod id="dashboard" data='{"stats": {}, "user": {}}' *fetch="/api/stats.json:stats">
  <h2>Dashboard</h2>
  <section>
    <p>Total users: <span *print="stats.totalUsers"></span></p>
    <p>Active users: <span *print="stats.activeUsers"></span></p>
  </section>
</serc-rod>

Non-clickable auto fetch:

<serc-rod id="news" data='{"articles": []}'>
  <section *fetch="/api/news.json:articles">
    <h2>Latest news</h2>
    <ul *each="article of articles">
      <li>
        <strong *print="article.title"></strong>
        <p *print="article.summary"></p>
      </li>
    </ul>
  </section>
</serc-rod>

Clickable reload button:

<serc-rod id="log-viewer" data='{"log": []}'>
  <button *fetch="/api/log.json:log">
    Reload log
  </button>

  <ul *each="entry of log">
    <li *print="entry.message"></li>
  </ul>
</serc-rod>

Notes