Async Actions & Toast Notifications
Fire a button's handler asynchronously with loading/success text states, and queue a toast notification from inside a hook or button function.
Loading/success text on a button
A ->button() call's before/loading/after options drive the button's text through each phase of an async click - idle, in-flight, and briefly on success - using the same spinner treatment Save/Delete already get (setButtonLoading() in core/xcrud.js):
$xcrud->button('Process', 'orderdetails_process_line', [
'icon' => 'fa fa-cogs',
'confirm' => 'Process this order line?',
'before' => 'Process',
'loading' => 'Processing…',
'after' => 'Processed ✓',
]);
See Custom Row Buttons for the full option list.
Queuing a toast
toast($message, $type = 'success') queues a message for xcrud.js's own toast-popup UI. Call it from inside a hook or button handler - not from a page's top-level PHP, since nothing reads it outside a write request:
function payments_after_insert(mixed $id, array $row, Xcrud $xcrud): void
{
$xcrud->toast('Payment recorded.');
}
$type is a free-form string; xcrud.js recognizes 'success'/'error'/'info'/'warning' for styling/icon and falls back to 'info' for anything else, so a typo degrades to a plain-colored toast rather than silently vanishing.
Using it on a page with no grid at all
Async loading states and toasts aren't tied to a mounted $xcrud widget - Xcrud::uiAssets() loads just the current theme's CSS/JS, and core/xcrud.js exposes window.Xcrud.setButtonLoading()/window.Xcrud.toast() directly, so a widget-less page can reuse the exact same spinner/toast treatment on its own plain button:
<body>
<?php echo Xcrud::uiAssets(); ?>
<script src="core/xcrud.js"></script>
<button type="button" id="demo-async-btn">Generate Report</button>
<script>
var btn = document.getElementById('demo-async-btn');
btn.addEventListener('click', function () {
window.Xcrud.setButtonLoading(btn, true, 'Processing…', 'none');
fetch('core/demo_async.php', { method: 'POST' })
.then(function (res) { return res.json(); })
.then(function (json) {
window.Xcrud.setButtonLoading(btn, false, '', 'none');
window.Xcrud.toast(json.message || 'Done.', json.success ? 'success' : 'error');
})
.catch(function () {
window.Xcrud.setButtonLoading(btn, false, '', 'none');
window.Xcrud.toast('Network error.', 'error');
});
});
</script>
</body>
Place Xcrud::uiAssets() and the xcrud.js <script> tag in <body>, not <head> - the router's shell-wrapping extracts only the <body> contents out of a page that produces its own full HTML document, so a <head>-only asset tag never reaches the final page.
Reference
| Call | Purpose |
|---|---|
window.Xcrud.setButtonLoading(btn, isLoading, loadingText, ui) | Toggles a button between idle and loading state (disabled, spinner, replacement text) - the same helper Save/Delete/->button() clicks already use internally. |
window.Xcrud.toast(message, type) | Shows a toast popup client-side directly, without a server round trip queuing it. |
$xcrud->toast($message, $type = 'success') | Queues a toast server-side, from inside a hook/button function, delivered on the next response. |
Xcrud::uiAssets() | Emits the current theme's CSS/JS tags without mounting a widget - for a page that wants xcrud.js's helpers but has no grid. |