AJAX Functions Reference
APD provides a set of AJAX functions for communicating with Business Central without page refreshes.
Core AJAX Functions
ajax_request(url, data, callback, context)
Low-level AJAX request function.
Parameters:
| Parameter | Type | Description |
|---|---|---|
| url | string | Request URL |
| data | string | POST data |
| callback | function | Callback for async (null for sync) |
| context | object | Context passed to callback |
Returns: ajax_response object (for sync requests)
Example:
// Synchronous request
var response = ajax_request(
RootLocation + '?action=MYACTION',
'param1=value1¶m2=value2',
null,
null
);
// Asynchronous request
ajax_request(
RootLocation + '?action=MYACTION',
'param1=value1',
function(response) {
if (response.error) {
console.error(response.error);
} else {
console.log(response.value);
}
},
{ myContext: 'data' }
);
ajax_response Object
The response object returned by AJAX requests.
Properties:
| Property | Type | Description |
|---|---|---|
| request | XMLHttpRequest | The raw request object |
| error | ajax_error | Error object if failed |
| value | string | Response text if successful |
| context | object | Context from request |
ajax_error Object
Error information for failed requests.
Properties:
| Property | Type | Description |
|---|---|---|
| name | string | Error name |
| description | string | Error description |
| number | number | Error code |
ajax_stop()
Aborts all pending AJAX requests.
Usage:
// Cancel all pending requests
ajax_stop();
APD AJAX Functions
APD_GetAction(action, parms)
Calls an APD action and returns the response.
Parameters:
| Parameter | Type | Description |
|---|---|---|
| action | string | Action code |
| parms | string | URL parameters |
Returns: Response text
Example:
var html = APD_GetAction('PRODUCT-DETAILS', 'itemno=ITEM001');
document.getElementById('product-panel').innerHTML = html;
APD_Refresh(table, inputForm)
Refreshes form fields with current record data.
Parameters:
| Parameter | Type | Description |
|---|---|---|
| table | number | Table number |
| inputForm | HTMLFormElement | Form to refresh |
Returns: true if successful, false if no data
Example:
function refreshCustomer() {
var form = document.getElementById('customerForm');
if (!APD_Refresh(18, form)) {
APDAlert('Customer not found');
}
}
APD_Find(table, step, viewString, inputForm, outputForm)
Finds records in a table with navigation.
Parameters:
| Parameter | Type | Description |
|---|---|---|
| table | number | Table number |
| step | string | Navigation direction |
| viewString | string | Filter string |
| inputForm | string | Form name for input data |
| outputForm | string | Form name for output data |
Step Values:
| Value | Description |
|---|---|
- |
First record |
+ |
Last record |
< |
Previous record |
> |
Next record |
= |
Exact match |
Returns: true if found, false if not
Examples:
// Find first customer
APD_Find(18, '-', 'undefined', 'custForm', 'custForm');
// Find next customer
APD_Find(18, '>', 'undefined', 'custForm', 'custForm');
// Find with filter
APD_Find(18, '-', 'WHERE(Name=FILTER(@*Smith*))', 'custForm', 'custForm');
APD_Insert(form, table)
Inserts a new record from form data.
Parameters:
| Parameter | Type | Description |
|---|---|---|
| form | HTMLFormElement | Form containing data |
| table | number | Table number |
Example:
<form id="newItemForm">
<input type="text" name="27:3" placeholder="Description">
<input type="number" name="27:18" placeholder="Unit Price">
<button onclick="APD_Insert(this.form, 27)">Create</button>
</form>
Result Handling:
// Form fields are updated with the inserted record data
// Including any auto-generated values like No.
APD_Modify(form, table)
Modifies an existing record.
Parameters:
| Parameter | Type | Description |
|---|---|---|
| form | HTMLFormElement | Form containing data |
| table | number | Table number |
Example:
<form id="editForm">
<input type="hidden" name="TABLE" value="18">
<!-- Primary key as a hidden input (APD_Modify reads form elements;
<?key?> would only write a URL query fragment) -->
<input type="hidden" name="18:1" value="<?field(Customer,"No.")?>">
<!-- Editable fields -->
<input type="text" name="18:2" value="<?field(Customer,Name)?>">
<button onclick="APD_Modify(this.form, 18)">Save</button>
</form>
APD_FillLines(tableNo, parentTableNo, viewString)
Fills multiple forms with line records.
Parameters:
| Parameter | Type | Description |
|---|---|---|
| tableNo | number | Line table number |
| parentTableNo | number | Parent table number |
| viewString | string | Filter with parent reference |
Example:
// Fill sales lines for current order
APD_FillLines(37, 36, 'WHERE(Document No.=FILTER(?1?))');
Session Functions
APD_Set(key, value)
Stores a value in the server session.
Parameters:
| Parameter | Type | Description |
|---|---|---|
| key | string | Storage key |
| value | string | Value to store |
Returns: true if successful
Example:
// Store user preference
APD_Set('theme', 'dark');
APD_Set('lastCustomer', '10000');
APD_Get(key)
Retrieves a value from the server session.
Parameters:
| Parameter | Type | Description |
|---|---|---|
| key | string | Storage key |
Returns: Stored value or null
Example:
var theme = APD_Get('theme');
if (theme === 'dark') {
document.body.classList.add('dark-mode');
}
APD_Has(key)
Checks if a key exists in session.
Parameters:
| Parameter | Type | Description |
|---|---|---|
| key | string | Storage key |
Returns: true if exists
Example:
if (APD_Has('cart')) {
loadCart();
}
Response Handling
Response Prefixes
APD_validate, APD_Find, APD_Refresh, APD_Insert, and APD_Modify return responses that start with a 5-character prefix:
| Prefix | Meaning | Returned by |
|---|---|---|
DATA1 |
Success — followed by URL-encoded name=value pairs for the form fields |
All of the above |
ERROR |
Error — followed by the error message text | All of the above |
EMPTY |
No record matched the search | APD_Find, APD_Refresh |
APD_GetAction does not use these prefixes — it returns the action's raw response body. The other functions are wrappers around APD_validate's envelope-parsing logic and you don't normally inspect the prefix yourself.
Parsing Data Response
if (response.value.slice(0, 5) === 'DATA1') {
var data = response.value.slice(5);
var pairs = data.split('&');
var fields = {};
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
fields[pair[0]] = decodeURIComponent(pair[1]);
}
// Use fields object
console.log(fields['18:2']); // Customer Name
}
Error Handling
Default Error Handler
APDAlert = function(message) {
alert(message);
};
Custom Error Handler
APDAlert = function(message) {
// Show in custom modal
var modal = document.getElementById('errorModal');
modal.querySelector('.message').textContent = message;
modal.style.display = 'block';
};
Error from URL
APD can pass errors via URL:
// Automatic error display on page load
if (window.location.search.search("_ERRORMESSAGE") !== -1) {
setTimeout(APD_ShowError, 1000);
}
Utility Functions
enc(s)
Encodes special characters for URL.
var encoded = enc('Hello=World&More');
// Returns: Hello%3DWorld%26More
APD_GetValueFromQueryString(parm)
Gets a parameter from the URL.
var customerId = APD_GetValueFromQueryString('custno');
APD_CreateViewString(parentTableNo, viewString)
Creates a view string with parent field values.
var view = APD_CreateViewString(36, 'WHERE(Document No.=FILTER(?1?))');
// Replaces ?1? with value of field 1 from table 36
Best Practices
Async vs Sync
- Use async for user-initiated actions
- Avoid sync requests (blocks UI)
Error Recovery
function safeAjax(action, data, callback) {
try {
ajax_request(
RootLocation + '?' + action,
data,
function(response) {
if (response.error) {
APDAlert('Request failed: ' + response.error.name);
} else {
callback(response);
}
},
null
);
} catch (e) {
APDAlert('Network error. Please try again.');
}
}
Loading Indicators
function withLoading(action) {
showSpinner();
action().finally(function() {
hideSpinner();
});
}