sercrod

*into

Summary

*into selects a data slot that receives the result of certain Sercrod directives that talk to the outside world. It is most often used together with *api, *upload, or *websocket to capture responses in a named field on the root data object.

*into has an alias n-into. Both forms behave the same.

Key points:

Basic example

Capture an API response into user:

<serc-rod id="app" data='{"user": null}'>
  <button
    *api="'/api/user.json'"
    method="GET"
    *into="user"
  >
    Load user
  </button>

  <pre *if="user" *print="JSON.stringify(user, null, 2)"></pre>
</serc-rod>

Behavior:

Behavior

*into is a routing hint for Sercrod’s I/O helpers. It tells those helpers which top-level key on the root data object should receive their latest result.

Implemented behavior in this version:

No other directives read *into in the current implementation. Putting *into on an element that does not participate in these features has no effect.

Evaluation timing

*into is always read on the element that owns the directive which uses it.

Execution model

At a high level, the execution model for *into looks like this for each supported directive.

Variable creation and scope layering

*into does not create new variables for expressions. Instead, it targets the root data object:

There is no special $into variable or local binding created by *into itself.

Scope layering and parent access

Because *into writes to the root data object, scope behaves as follows:

*into does not introduce any extra scope layers by itself.

Use with *api

*into is most directly tied to the *api / n-api logic.

Key behaviors:

Typical patterns:

<!-- GET: store response into "user" and also into $download -->
<button *api="'/api/user.json'" method="GET" *into="user">
  Load user
</button>

<!-- POST: store result into "result" and also into $upload -->
<button
  *api="'/api/save'"
  method="POST"
  body="{ name: form.name }"
  *into="result"
>
  Save
</button>

If you need to keep the data beyond one update cycle, copy it to a stable field in an event handler or effect, instead of relying on the short-lived *into slot.

Use with *upload

For uploads, *into is read from the element that defines the upload behavior and is then used on the hidden file input.

Behavior:

Example pattern:

<serc-rod
  data='{
    "uploadResult": null
  }'
>
  <button
    *upload="{ url: '/api/upload', accept: 'image/*' }"
    *into="uploadResult"
  >
    Upload image
  </button>

  <p *if="uploadResult">
    Uploaded: <span *print="uploadResult.fileName"></span>
  </p>
</serc-rod>

In this pattern:

Use with *websocket

*into is also supported on WebSocket hosts.

Behavior:

If the *websocket expression resolves to an object with an into property, Sercrod also respects that, but a markup *into on the same element takes priority.

Example:

<serc-rod id="ws-app" data='{"lastMessage": null}'>
  <section
    *websocket="'wss://example.com/live'"
    *into="lastMessage"
  >
    <p>Connection status: <span *print="$ws_ready ? 'ready' : 'connecting'"></span></p>
    <p *if="lastMessage">Last message: <span *print="JSON.stringify(lastMessage)"></span></p>
  </section>
</serc-rod>

Best practices

Examples

Capture download status separately for GET and POST:

<serc-rod
  data='{
    "user": null,
    "saveResult": null
  }'
>
  <button *api="'/api/user'" method="GET" *into="user">
    Load user
  </button>

  <button
    *api="'/api/user'"
    method="POST"
    body="{ user }"
    *into="saveResult"
  >
    Save user
  </button>

  <section *if="user">
    <h2>User</h2>
    <pre *print="JSON.stringify(user, null, 2)"></pre>
  </section>

  <section *if="saveResult">
    <h2>Last save result</h2>
    <pre *print="JSON.stringify(saveResult, null, 2)"></pre>
  </section>
</serc-rod>

Use *into with WebSocket messages:

<serc-rod data='{"ticker": null}'>
  <div
    *websocket="{ url: 'wss://example.com/ticker', into: 'ticker' }"
  >
    <p *if="ticker">
      Price: <span *print="ticker.price"></span>
    </p>
  </div>
</serc-rod>

Notes