/

Entkoppelte Frontends & CORS

Ein Xcrud-Widget - oder nur seine Toast-/Spinner-Helfer - von einem Frontend aus einbinden, das gar keine PHP-Seite ist.

window.Xcrud.mount()

Clientseitig ist jedes Xcrud-Widget ein reines JavaScript-Objekt. core/xcrud.js stellt einen globalen Helfer bereit, der eines direkt an einem Mount-Punkt konstruiert, ganz ohne PHP-render()-Aufruf:

<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>

So bindet ein vollständig statisches Frontend (eine reine HTML-Datei, eine separate SPA) ein Grid ein, das mit einem xCRUD-Nova-Pro-Backend spricht, mit dem es keine PHP-Laufzeitumgebung teilt. Der Mount-Punkt benötigt weiterhin zuerst die Assets des passenden Themes - siehe Xcrud::uiAssets() in der Konfigurationsreferenz.

Helfer ohne Widget

Dieselbe globale Variable stellt auch die UI-Feedback-Helfer bereit, die jedes eingebundene Grid intern bereits verwendet, sodass eine Seite ganz ohne Grid - nur mit einem Button, sagen wir - genau denselben Look wiederverwenden kann:

FunktionBeschreibung
Xcrud.toast(message, type)Zeigt dieselbe Toast-Benachrichtigung, die eine Speichern-/Löschen-Aktion oder der eigene ->toast()-Aufruf eines Hooks anzeigen würde.
Xcrud.spinnerHtml(ui)Liefert das Spinner-Markup des Themes als HTML-String. ui greift standardmäßig auf den eigenen Standard von XcrudConfig::$ui ('tailwind') zurück, wenn ausgelassen.
Xcrud.setButtonLoading(btn, isLoading, loadingLabel, ui)Wechselt einen Button zwischen normalem Zustand und Ladezustand (deaktiviert, Spinner, optionaler Beschriftungstausch) - dieselbe Behandlung, die jeder Speichern-/Löschen-Button während einer laufenden Anfrage erhält.
<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>

Genau dieses Muster verwendet pages/async-demo.php - eine Seite ganz ohne $xcrud-Widget, die Xcrud::uiAssets() und core/xcrud.js direkt lädt, um an diese globalen Funktionen zu kommen.

Serverseitige Konfiguration für domänenübergreifende Nutzung

Werden Frontend und Backend von unterschiedlichen Origins ausgeliefert, müssen mehrere XcrudConfig-Einstellungen von ihren Same-Origin-Standardwerten abweichen:

EigenschaftTypBeschreibung
$allowedOriginsarrayDie CORS-Whitelist - Origins, die ajax_crud.php domänenübergreifend aufrufen dürfen. Eine fehlende Frontend-Origin in dieser Liste ist die häufigste Ursache für einen browserseitigen "Netzwerkfehler", obwohl das Backend einwandfrei geantwortet hat.
$crossOriginSessionCookieboolBei true wird das Login-Session-Cookie auf SameSite=None; Secure umgestellt, damit es einen domänenübergreifenden fetch(..., {credentials: 'include'})-Aufruf übersteht. Nur nötig, wenn $loginAuthentication ebenfalls aktiv ist und das Frontend auf einer anderen Origin liegt. Erfordert einen echt sicheren Kontext (echtes HTTPS, oder beide Seiten auf localhost/127.0.0.1).
$forceApiUrlstringZwingt jedes Widget auf jeder Seite dazu, diese absolute URL für die API aufzurufen, statt der relativen Standardvorgabe core/ajax_crud.php - nötig, wenn das HTML von einer anderen Origin als die API ausgeliefert wird.
$forceUploadUrlstringDieselbe Idee für den Upload-Endpunkt.
$forceGalleryUrlstringDieselbe Idee für den Galerie-Endpunkt.
$forceMediaUrlstringDieselbe Idee für images_handler.php, den signierten Endpunkt, über den jede hochgeladene Datei tatsächlich ausgeliefert wird.
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';