Network & Data Fetching
Overview
Pragma CMS provides lightweight, native wrappers around the browser's Fetch API. These utilities automatically handle HTTP headers, Cross-Site Request Forgery (CSRF) protection, caching bypass, and global error UI state, eliminating the need for bulky third-party libraries like Axios.
apiRequest(url, options, loader, expectedType)
The universal engine for all asynchronous calls in the CMS. It automatically parses responses, catches HTTP errors (4xx, 5xx), triggers UI popups (displayErrorPopup), and integrates with the visual loader system.
Why use apiRequest instead of native fetch()?
- Automatic Error Handling: It parses JSON securely and catches HTTP errors (4xx, 5xx), automatically triggering a UI popup (
displayErrorPopup()) if something goes wrong. - Security: Automatically injects the
X-Requested-With: XMLHttpRequestheader to bypass page caching securely. - Multiple Formats: Easily handles
"json"(default),"html"(for DOM injection), and"blob"(for file downloads).
Signature:
async function apiRequest(url, options = {}, loader = null, expectedType = "json")
| Parameter | Type | Default | Description |
|---|---|---|---|
url | string | Required | The endpoint URL to call. |
options | object | {} | Standard Fetch API options (method, body, headers). Automatically injects X-Requested-With: XMLHttpRequest. |
loader | HTMLElement | null | A DOM element generated by showLoader(). It will be automatically removed when the request completes. |
expectedType | string | "json" | The expected response format: "json", "html" (for DOM injection), or "blob" (for file downloads). |
Returns: Promise<Object | string | Blob | null> (Returns null if the request fails, as the error is handled natively by the UI).
Example 1: Posting FormData
const form = document.getElementById('my-form');
const submitBtn = document.getElementById('submit-btn');
// 1. Attach a loader to the button
const loader = showLoader(submitBtn, [], { '--size': '24px' }, 'append');
// 2. Send the request
const response = await apiRequest('/api/settings', {
method: 'POST',
body: new FormData(form)
}, loader);
// 3. Handle response
if (!response) return; // Request failed and error popup is already displayed
if (response.success) {
displaySuccessPopup(response.message);
}
Example 2: Downloading a File (Blob)
const blob = await apiRequest('/api/backups/download', { method: 'GET' }, null, "blob");
if (blob) {
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = "backup.zip";
link.click();
URL.revokeObjectURL(link.href);
}
apiFetch(endpoint, searchTerm, langId, extraParams)
Built on top of apiRequest, this function specifically formats URLs to query CMS content (Entries, Taxonomies, Users). It automatically builds the query string and expects a { data: [...] } structure in the JSON response.
Example: Live Search for Categories
const searchInput = "tech";
const currentLangId = window.CMS.currentLangId;
const response = await apiFetch("taxonomies/blog_category/terms", searchInput, currentLangId, {
root_term_id: 12,
limit: 10
});
if (response && response.data) {
renderDropdown(response.data);
}
handleLangChange(endpoint, params, updateCallback)
Standardizes the workflow for changing the active language in the Admin UI. It fetches the translated data for a specific entry/page and executes a callback to update the DOM.
Signature:
async function handleLangChange(endpoint, params = {}, updateCallback)
Example:
const langSelect = document.querySelector("#lang-id-page");
langSelect.addEventListener("change", () => {
const params = { "lang_id": langSelect.value, "page_id": 42 };
handleLangChange("pages", params, (result, langId) => {
// Update DOM inputs with the newly fetched translated data
document.querySelector("#title").value = result.data.page.title || '';
});
});
Data Handling & Normalization
normalizeApiData(data)
Since Pragma CMS APIs may return collections under semantic keys (e.g. menuItems, articles, children, etc.), this utility provides a lightweight normalization layer for frontend components.
It scans the response object and returns the first array it can identify.
This allows UI components to remain decoupled from specific API field names while still working with evolving or extended response structures.
Why use it?
- Prevents tight coupling between UI components and API response structure
- Allows API responses to evolve without breaking frontend code
- Supports optional metadata wrappers (pagination, counts, filters, etc.)
- Enables generic rendering components across different content types
{ data: [...] }).Usage Example
const response = await apiFetch("my/custom/resource");
// Example response:
// {
// data: {
// projects: [...],
// count: 12
// }
// }
const items = normalizeApiData(response.data);
items.forEach(item => {
console.log(item.title);
});
Signature
function normalizeApiData(data)
Parameters
| Parameter | Type | Description |
|---|---|---|
data | `Object | Array` |
Returns
Array
Returns the first detected array inside the provided data structure.
If no array is found, returns an empty array ([]).
Design Note (Important)
In Pragma CMS, the normalizeApiData() function should be considered a graceful normalization helper, not a core architectural dependency.
For production-grade consistency, API responses are expected to follow a strict contract:
{
"data": []
}
Using normalizeApiData is primarily intended for:
- legacy endpoints
- flexible integrations
- rapid UI prototyping
- transitional API states