Frontends découplés & CORS
Monter un widget Xcrud - ou seulement ses helpers de toast/spinner - depuis un frontend qui n'est pas du tout une page PHP.
window.Xcrud.mount()
Chaque widget Xcrud est, côté client, un simple objet JavaScript. core/xcrud.js expose un helper global qui en construit un directement contre un point de montage, sans qu'aucun appel PHP render() ne soit impliqué :
<div id="payments-grid"></div>
<script src="core/xcrud.js"></script>
<script>
window.Xcrud.mount('payments-grid', {
route: 'payments',
api: 'https://api.example.com/core/ajax_crud.php'
});
</script>
C'est la forme qu'utilise un frontend entièrement statique (un simple fichier HTML, une SPA séparée) pour intégrer une grille qui communique avec un backend xCRUD Nova Pro avec lequel il ne partage aucun runtime PHP. Le point de montage a quand même besoin que les assets du thème correspondant soient chargés au préalable - voir Xcrud::uiAssets() dans la Référence XcrudConfig.
Helpers sans widget
Le même objet global expose aussi les helpers de retour visuel que toute grille montée utilise déjà en interne, de sorte qu'une page sans aucune grille - juste un bouton, par exemple - peut réutiliser exactement le même rendu :
| Fonction | Description |
|---|---|
Xcrud.toast(message, type) | Affiche la même notification toast qu'une action Enregistrer/Supprimer ou qu'un appel ->toast() propre à un hook. |
Xcrud.spinnerHtml(ui) | Retourne le balisage du spinner du thème sous forme de chaîne HTML. ui retombe sur la valeur par défaut de XcrudConfig::$ui ('tailwind') si omis. |
Xcrud.setButtonLoading(btn, isLoading, loadingLabel, ui) | Fait basculer un bouton entre son état normal et son état de chargement (désactivé, spinner, changement de libellé optionnel) - le même traitement que subit chaque bouton Enregistrer/Supprimer pendant qu'une requête est en cours. |
<button id="run-report">Generate Report</button>
<script>
var btn = document.getElementById('run-report');
btn.addEventListener('click', function () {
window.Xcrud.setButtonLoading(btn, true, 'Processing…');
fetch('core/demo_async.php', { method: 'POST' })
.then(function (res) { return res.json(); })
.then(function (json) {
window.Xcrud.setButtonLoading(btn, false);
window.Xcrud.toast(json.message || 'Done.', json.success ? 'success' : 'error');
});
});
</script>
C'est exactement le schéma qu'utilise pages/async-demo.php - une page sans aucun widget $xcrud, qui charge Xcrud::uiAssets() et core/xcrud.js directement pour obtenir ces objets globaux.
Configuration serveur pour un usage cross-origin
Lorsque le frontend et le backend sont servis depuis des origines différentes, plusieurs réglages XcrudConfig doivent s'écarter de leurs valeurs par défaut prévues pour une même origine :
| Propriété | Type | Description |
|---|---|---|
$allowedOrigins | array | La liste blanche CORS - les origines autorisées à appeler ajax_crud.php en cross-domain. Une origine frontend absente de cette liste est la cause la plus fréquente d'une "erreur réseau" côté navigateur, alors même que le backend a répondu correctement. |
$crossOriginSessionCookie | bool | Lorsque true, bascule le cookie de session de connexion vers SameSite=None; Secure pour qu'il survive à un appel fetch(..., {credentials: 'include'}) cross-origin. Nécessaire uniquement lorsque $loginAuthentication est également activé et que le frontend est sur une origine différente. Requiert un contexte réellement sécurisé (vrai HTTPS, ou les deux côtés sur localhost/127.0.0.1). |
$forceApiUrl | string | Force chaque widget de chaque page à appeler cette URL absolue pour l'API, au lieu de la valeur relative par défaut core/ajax_crud.php - nécessaire lorsque le HTML est servi depuis une origine différente de l'API. |
$forceUploadUrl | string | Même principe pour le endpoint d'upload. |
$forceGalleryUrl | string | Même principe pour le endpoint de galerie. |
$forceMediaUrl | string | Même principe pour images_handler.php, le endpoint signé par lequel chaque fichier téléversé est effectivement servi. |
public static array $allowedOrigins = ['https://app.example.com'];
public static bool $crossOriginSessionCookie = true;
public static string $forceApiUrl = 'https://api.example.com/core/ajax_crud.php';
public static string $forceUploadUrl = 'https://api.example.com/core/upload.php';
public static string $forceMediaUrl = 'https://api.example.com/core/images_handler.php';