data-fetch System
This system allows transforming links and containers with the attribute
data-fetch="get" or data-fetch="post"
into asynchronous fetch() calls.
The request is sent automatically (on click for links, on page load for divs),
and the JSON response is handled in a unified way (modals, offcanvas, toasts, HTML replacement...).
- Links (
<a>): Fetch triggered on click - Containers (
<div>): Fetch triggered automatically on page load
1. data-fetch Links
Transform any link into an asynchronous fetch call that triggers on click.
<a href="/example/url?param=1" data-fetch="get" class="btn btn-primary">
Fetch GET example
</a>
<a href="/example/url?user=42&active=1" data-fetch="post" class="btn btn-secondary">
Fetch POST example
</a>
Demo Fetch Links
Clicking these buttons will trigger a fetch call instead of navigation:
Fetch GET Fetch POSTWhen a link is clicked:
- It is given the
disabledclass (Bootstrap-compatible) to prevent double clicks. - A
fetch()call is executed (GETorPOST). - The response must always be in JSON format.
- Depending on the returned data, it can open
modals,offcanvas, ortoasts. - Once the request is completed, the link is re-enabled.
Example JSON Response
{
"success": true,
"msg": "Operation completed successfully",
"modal": {
"title": "Success",
"body": "The operation was completed successfully.",
"footer": "<button class='btn btn-primary' data-bs-dismiss='modal'>Close</button>"
}
}
If the JSON response contains these properties, they are automatically handled:
msg→ shows a toast ifwindow.toastsexistsmodal→ opens a modal viawindow.modal.show()offcanvas_end→ opens an offcanvas viawindow.offcanvasEnd.show()
This is used in the builder title as an option in addButton
You can call initFetchLinks() again after a dynamic DOM update
to reinitialize new links added via AJAX.
Redirects are also supported:
{
"success": true,
"redirect": "/example/url"
}
2. data-fetch Containers (Divs)
Containers with data-fetch and data-url attributes automatically load content via fetch when the page loads.
This is perfect for loading tables, dashboards, or any dynamic content without blocking the initial page render.
Basic Usage
<div id="tableContainer"
data-fetch="post"
data-url="?page=posts&action=get-table">
<!-- Content will be loaded here automatically -->
</div>
- Faster page load: The page renders immediately, content loads progressively
- Non-blocking: Multiple containers load sequentially without blocking each other
- Automatic: No JavaScript code needed, just add the attributes
- Clean HTML: Attributes are removed after loading to keep DOM clean
How it Works
- Page finishes loading (DOMContentLoaded)
- After 500ms, the first div with
data-fetchstarts loading - Each subsequent div loads 500ms after the previous one
- The response (JSON) is handled by
jsonAction()with the div as container - The
data-fetchanddata-urlattributes are removed to prevent re-loading
Sequential Loading
If you have multiple containers, they load in sequence with 500ms delay between each:
<!-- Loads at 500ms -->
<div data-fetch="post" data-url="?page=stats&action=get-summary"></div>
<!-- Loads at 1000ms (1s) -->
<div data-fetch="post" data-url="?page=posts&action=get-table"></div>
<!-- Loads at 1500ms (1.5s) -->
<div data-fetch="post" data-url="?page=comments&action=get-recent"></div>
- T+0ms: Page loads
- T+500ms: First container starts loading
- T+1000ms: Second container starts loading
- T+1500ms: Third container starts loading
- And so on...
Controller Response
The controller should return JSON with html to replace the container content:
<?php
#[RequestAction('get-table')]
public function getTable() {
$table = TableBuilder::create($this->model, 'idTable')
->activeFetch()
->asLink('title', '?page='.$this->page.'&action=edit&id=%id%')
->setDefaultActions();
if ($table->isInsideRequest()) {
// When table updates itself (pagination, sorting)
Response::Json(['html' => $table->render()]);
} else {
// When loaded initially or from external fetch
Response::Json([
'modal' => [
'title' => $this->title,
'body' => $table->render(),
'size' => 'xl'
]
]);
}
}
Alternative: HTML Replacement
You can also return HTML that replaces the container directly:
<?php
Response::Json([
'html' => '<div class="table-responsive">...</div>'
]);
The html property in the response will replace the container's outerHTML.
Error Handling
If the fetch fails, the container will show an error message:
<div class="alert alert-danger">Failed to load content</div>
The data-fetch and data-url attributes are removed even on error to prevent infinite retry loops.
Loading Indicator
If window.plugin_loading is available, it will be shown during the fetch operation and hidden when complete.
Manual Re-initialization
If you dynamically add containers after page load, you can manually trigger the initialization:
// After adding new containers to DOM
window.initFetchDiv();
Complete Example: Dashboard with Multiple Sections
<div class="container-fluid">
<div class="row">
<!-- Stats cards - loads first at 500ms -->
<div class="col-12 mb-4"
data-fetch="post"
data-url="?page=dashboard&action=get-stats">
<div class="text-center py-5">
<div class="spinner-border" role="status"></div>
<p>Loading statistics...</p>
</div>
</div>
<!-- Recent posts table - loads second at 1000ms -->
<div class="col-md-6 mb-4"
data-fetch="post"
data-url="?page=posts&action=get-recent">
<div class="text-center py-5">
<div class="spinner-border" role="status"></div>
<p>Loading recent posts...</p>
</div>
</div>
<!-- Activity log - loads third at 1500ms -->
<div class="col-md-6 mb-4"
data-fetch="post"
data-url="?page=activity&action=get-log">
<div class="text-center py-5">
<div class="spinner-border" role="status"></div>
<p>Loading activity...</p>
</div>
</div>
</div>
</div>
Comparison: Links vs Containers
| Feature | Links (<a data-fetch>) |
Containers (<div data-fetch>) |
|---|---|---|
| Trigger | Click event | Automatic on page load |
| URL Source | href attribute |
data-url attribute |
| Loading Timing | Immediate on click | Sequential (500ms delay between each) |
| Disabled State | Yes (adds disabled class) |
No |
| Common Use Cases | Edit buttons, Delete actions, Form submissions | Tables, Dashboards, Stats, Dynamic content |
| Response Container | link.parentNode |
The div itself |
| Attributes Removed | No | Yes (after loading) |
Summary
- Links:
<a href="..." data-fetch="post">- Triggers on click - Containers:
<div data-fetch="post" data-url="...">- Auto-loads on page load - Methods:
getorpost - Response: Always JSON format
- Handler:
jsonAction(data, container) - Re-init:
window.initFetchLinks()andwindow.initFetchDiv()