Lifecycle (advanced): fetch and post
In the previous chapter, you saved and loaded data from local files and
(optionally) localStorage. In this step, Sercrod will talk to your server
using *fetch and *post.
*fetch- load JSON from a URL intodata.*post- send the currentdataas JSON.
Fetch JSON into one field
*fetch expects a URL, optionally followed by a placement key:
path/to.json[:key].
-
If
:keyis present, the JSON is stored into that top-level data key. -
If
:keyis omitted, the entiredatais replaced with the JSON.
Here is a small example that fetches a list into items and
renders it with *for.
Code
<serc-rod data='{"items":[]}' *fetch="/api/examples/items.json:items">
<h2>Items from the server</h2>
<ul>
<li *for="item of items">%item%</li>
</ul>
</serc-rod>
For this example, the server returns JSON like:
[
"Attribute-first",
"Tiny runtime",
"SSG / SSR friendly"
]
Sample
Items from the server
- %item%
When the host is connected, Sercrod calls fetch("/api/examples/items.json"),
parses the JSON, assigns it to data.items, and then re-renders.
Replace all data with *fetch
If you omit the placement key, Sercrod replaces the whole
data object with the fetched JSON. This is useful when your
server already returns exactly the structure you want to render.
Code
<serc-rod *fetch="/api/examples/profile.json">
<h2>%name%</h2>
<p>Role: %role%</p>
<p>Location: %location%</p>
</serc-rod>
For this example, the server returns JSON like:
{
"name": "Sercrod sample user",
"role": "Frontend developer",
"location": "Your browser"
}
Sample
%name%
Role: %role%
Location: %location%
In this pattern, the initial data is empty. After
*fetch completes, Sercrod wraps the JSON into its internal
data structure and updates the view.
POST current data with *post
*post attaches to a clickable element. When you click it,
Sercrod serializes the current data (or stage,
if present) to JSON and sends it to the given URL with
fetch() and POST.
Code
<serc-rod data='{"name":"", "email":"", "message":""}'>
<h2>Contact (demo)</h2>
<p>
<label>
Name:
<input type="text" *input="name" *lazy>
</label>
</p>
<p>
<label>
Email:
<input type="email" *input="email" *lazy>
</label>
</p>
<p>
<label>
Message:
<textarea *input="message" *lazy></textarea>
</label>
</p>
<p>
<button type="button" *post="/api/contact-demo">
Send as JSON
</button>
</p>
</serc-rod>
This form uses *lazy on the text fields. In a type-then-send
flow, the user usually types into a field and then immediately clicks the
send button. Without *lazy, committing the edited value may
cause the parent template to refresh at the same moment the button is
clicked. In that case, the first click can be used to commit the input and
move focus, instead of reaching the intended send action.
*lazy keeps this interaction natural. The input value is still
available to Sercrod, but the parent template is not refreshed on every
text edit. This makes form flows such as typing a message and clicking
Send easier to handle.
Use *eager instead when the page must react while the user is
typing, such as live search, live filtering, live preview, counters, or
immediate validation.
For live preview layouts, also read Nested Sercrod. It shows how to keep the input owner and the preview renderer as separate parent/child hosts.
Sample
Contact (demo)
On sercrod.com, /api/contact-demo is just a small stub
endpoint. It accepts the POST and returns a simple success response.
This guide does not cover the server code; implement it in PHP or any
server-side language that fits your project.
In this demo, the page does not change visually. You can open the browser's Network panel to confirm that a POST request is sent when you click the button.
Where this fits in the lifecycle
*save and *load work with local files or
localStorage. *fetch and *post extend the
same idea to remote endpoints:
*fetch- pull JSON intodata.*post- push the currentdataas JSON.
Both directives are explicit and local to each Sercrod host, so you can keep network logic close to the template that depends on it.
Next: Binding & events (advanced)
In the next chapter, you will refine bindings and events further: conditional updates, more complex event patterns, and integrating with existing components.