Ajax Callback

Description

Define a user-defined ajax callback. The callback can be handled by an Xbasic function that is defined in the component, by a separate .a5w page, or by another page (.e.g., .php, .asp, etc.)

Discussion

The Ajax Callback Action Javascript can be used to generate the Xbasic callback function that is called. The Xbasic callback function can be saved in the component in the Xbasic Functions section of the component builder. The action can be accessed anywhere the Action Javascript editor is available, including Javascript events for controls and Javascript Actions.

Ajax Callback Properties

Submit data

Specify if data from the grid should be submitted to the server when the callback is made.

Data from the current row are only submitted for fields that are editable. Primary key values, however, are submitted regardless of whether the current row is editable or not.

Submit part

Specify the part from which data should be submitted. Choices include.

Row number

Specify which row in the grid to submit data from. The {Grid.Rownumber} placeholder is used to indicate the 'current row' in the Grid. To submit data from ALL of the rows in the grid, set Row Number to: All. To specify a new record row, use a negative number. e.g. -1 for the first new record row, -2 for the second new record row, etc.

Callback type

Specify the callback type. The callback can be handled by a Xbasic function, or by a page referenced by a URL. The function can be defined in the Grid (see 'Xbasic function declarations' section of the Grid), or in an .AEX file. Choices include.

Function name

Specify the Xbasic function name (do NOT include '()' in the name. e.g. specify name as 'myFunction', not 'myFunction()' ). The Xbasic function prototype must be: function functionName as c (e as p). The function must return Javascript code that you want to execute on the client. The 'e' parameter that is passed into the function contains all of the data submitted to the server on the callback.

Use the Firebug add-in for Firefox to see what data is submitted on the callback.

Click 'Create function prototype' for an example of the required syntax for the function.

URL

Specify the URL of the page that will handle the callback.

Action name

A variable called '_action' is passed to the URL. The value of _action is set to Action Name.

Advanced Properties

Additional data to submit

Specify any additional data that you want to submit to the server. This data must be in the form of a URL parameters string (i.e. name/value pairs) and it must be enclosed in single quotes. For example:

'_var1=alpha&_var2=beta'

The submitted data will be available in the e variable as properties with the same name. For example, for the above example string, the following e properties will be created:

e._var1 ' will contain "alpha"
e._var2 ' will contain "beta"

You can optionally compute the data to submit using JavaScript. For example, you might have a JavaScript function called gatherInfo() that returns some data to submit with the callback:

function gatherInfo() {
    return '_var1=alpha&_var2=beta';
}

You can specify that the gatherInfo() function should be called by entering the below in the Additional data to submit property:

gatherInfo()

The value returned by the function will be included in the data sent to the Ajax callback.

Compute current row data

If the current row is not editable, and the 'Submit Data' property is checked, field values from the current row are not submitted. Only the primary key values for the current row are submitted. However, if you check this box, then the server will query the database to retrieve the field values for the current row and make these values available to your callback handler.

IMPORTANT: To use this option in a read-only Grid based on SQL tables, you must ensure that you have defined the Primary Key for each table.

After callback complete Javascript

Specify any Javascript you want to execute when the callback is complete and all of the Javascript returned by the callback (if any) has executed.

images/ajcall.png
The 'After callback complete Javascript' property.

A Note on the 'After callback complete Javascript' Property

To specify the after callback complete Javascript in the UX or Grid's .ajaxCallback() method, you set the onComplete property in the optional optionsObject passed in. For example:

{dialog.object}.ajaxCallback('','','myXbasicFunction','','',{onComplete: function() { 
        alert('callback is complete')
    }
})

Location Data Properties

Submit location information

Specify if location information (longitude/latitude) should be submitted. The location information is obtained from the browser. The user will be prompted for permission to read location information. Not all browsers support retrieving location information.

The 'e' object passed to the Xbasic function will contain these properties:

__locationFound

true/false

__locationLatitude

the latitude value

__locationLongitude

the longitude value

High accuracy

If true, the device will use its most accurate method to get location information. If false, the device will use its fastest or lower power consumption method depending on the device.

Timeout

The amount of time in milliseconds to wait on the device to acquire location information excluding the amount of time it takes the user to grant the web page access to geolocation data.

Max age

The amount of time in milliseconds to accept a previously acquired location. 0 means that a new location must be acquired from the device.

Ajax Failed/Offline Javascript Properties

If the Ajax Callback fails because the client's device is online, these properties can be used to do fall-back processing -- such as notify the user that no network connection is available and that they should try again when they're connected to the Internet.

These properties are optional.

Timeout setting

Specify the time to wait (in milliseconds) for a response from the callback. If a response is not received within the specified time, the callback is considered to have failed and the 'onAjaxCallbackFailed' client-side event will be fired, and any Javascript defined in the optional 'Ajax failed Javascript' property will be executed. If you specify '<Default>' the global default value (defined in the {dialog.object}.ajaxCallbackTimeout property) will be used.

Ajax failed Javascript

Specify the Javascript to execute if the Ajax callback fails (i.e. if the server does not send a response).

Check if server is available

If enabled, performs a check to ensure the server is available (can be reached) before attempting to make the Ajax Callback. When you turn this property on, you can specify how long to wait for a response from the server before concluding that the server is not available.

To specify the time to wait, set the Timeout property. By default this property is set to 2000 ms. That means that if the server does not respond within 2000 ms, the server is considered to not be available.

If the server is unavailable, the JavaScript specified in the Server not available Javascript property will be executed and the Ajax callback will not be sent to the server.

Timeout

The amount of time to wait in milliseconds for the server to respond when checking for server availability. Defaults to 4000.

This property is shown when Check if server is available has been checked.

Server not available Javascript

Optional JavaScript to execute when the server is unavailable (no response has been received within the specified Timeout).

This property is shown when Check if server is available has been checked.

Perform a speed test before sending the Ajax request

Whether or not a speed test should be run before making the callback. A speed test determines if the quality of the connection to the server is good enough to perform the callback.

When you turn this property on you can specify how much data to send to the server to perform the speed test in the Amount of data to send property. By default this is set to .1MB (100KB).

You must also specify a maximum time to wait for the server to respond in the Maximum duration property. If the server does not respond within the specified amount of time, the speed test is considered to have failed.

If the speed test fails, the JavaScript specified in the Speed test failed Javascript property will be executed and the Ajax callback will not be made.

This property is shown when Check if server is available has been checked.

Amount of data to send

The amount of data to send for the speed test. The data amount is specified in megabytes using the format numberMB where number is the number of megabytes to send. For example, to send 100 kilobytes, you would enter .1MB. Defaults to .1MB.

This property is shown when Check if server is available and Perform a speed test before sending the Ajax request are checked.

Maximum duration (milliseconds)

The length of time in milliseconds to wait for the speed test to complete. If the test fails to complete in the alloted time, the connection to the server is determined to be too slow and the Ajax Callback is not sent. Defaults to 300.

This property is shown when Check if server is available and Perform a speed test before sending the Ajax request are checked.

Speed test failed Javascript

Optional JavaScript to execute when the speed test fails.

This property is shown when Check if server is available and Perform a speed test before sending the Ajax request are checked.

Offline Javascript

Specify the Javascript to execute if the device is offline. Since the device is offline, the Ajax callback is not made. Therefore the code in the 'Ajax failed Javascript' property will not get executed.

Chunked Responses

When an Ajax Callback is made, the user will not receive a response until the callback completes -- or a timeout is reached and the client gives up waiting for a response. Long-running processes can have the appearance of a browser hang if the user is unaware that the action they've performed will take a while. In this situation, you may want to send periodic updates to the user notifying them that the process is still running.

You can send intermediate responses from the Xbasic function to the client by enabling "Chunked Responses". A "Chunked Response" is a message sent from the Ajax Callback function to the client while the function continues to execute.

To enable chunked responses from your Ajax Callback, check the Allow chunked responses property.

images/chunkedResponses.png

In order to use chunked responses on IIS or Alpha Cloud, you must enable JIT Sessions. On Alpha Cloud, the JIT Sessions option is available in the Deployment dialog.

Enabling Allow chunked responses exposes the following properties:

Property
Description
Maximum number of messages

The maximum number of chunked responses that the client will handled. Set to -1 for no limit. Default is -1.

Maximum duration for callback

Set the maximum amount of time (in seconds) to allow for the callback function to complete processing. If your function takes longer than the specified time, the callback is terminated and any additional messages set to the client are ignored.

To send intermediate messages from your Ajax Callback function, use the a5AjaxChunkedResponseWrite() function. The a5AjaxChunkedResponseWrite() function takes one parameter -- a string that contains JavaScript to execute on the client. For example:

DIM js AS C
js = "$('div').innerHTML = 'Still working...';"
a5AjaxChunkedResponseWrite(js)

To learn more, download the example component and watch the video, "Chunked Responses - Sending Intermediate Responses to the Client", in the Videos section below.

Using Action Javascript to Write an Ajax Callback Function

  1. In the event editor with Action Javascript mode selected, click the Add button to add a new action.

    images/ajaxCallback1.png
  2. Select the Ajax Callback action and click OK.

    images/ajaxCallback2.png
  3. Define the name for the callback function that will be called. In the image below, a new function will be created that performs the callback called myCallback

    images/ajaxCallback3.png
  4. Define any additional (optional) data to submit to the callback function. Parameters sent to the callback function can be accessed through the e object in the Xbasic function.

    images/ajaxCallback4.png
  5. Click the Create function prototype link to generate the function prototype for the Ajax callback.

    images/ajaxCallback5.png
  6. Click the Copy to clipboard button to copy the function signature to the clipboard. When the code has been copied to the clipboard, click the Close button to close the dialog.

    images/ajaxCallback6.png
  7. Click the Open Xbasic Function Declarations link to open the Xbasic Function Declarations dialog. This is a shortcut to the Xbasic Functions section.

    images/ajaxCallback7.png
  8. Paste the code from the clipboard into the window and click OK.

    images/ajaxCallback8.png
  9. Click OK to save the Ajax Callback action.

  10. Optionally, add a comment that describes the action when prompted. Then, click the OK button.

    images/ajaxCallback9.png
  11. Click the Save button to save the changes made to the event or Javascript Action.

    images/ajaxCallback10.png
  12. Navigate back to the component builder. Expand the Code section in the far left column and click on Xbasic functions. This is where you can make changes to the Xbasic callback function you created using the Ajax Callback Action Javascript builder.

    images/ajaxCallback11.png

Making Callbacks from Javascript

It's best to use Action Javascript if it's available to add functionality to an application. If you would rather make a callback using Javascript, however, the .ajaxCallback() method for the Grid or UX Component is available. To learn more, visit the Grid Component or UX Component Client API documentation for the .ajaxCallback() method.

Variables Passed to the Xbasic Callback Function

The Xbasic function that handles the callback will be passed a dot variable called e with the following properties:

tmpl

The component definition.

__si

Component state information passed between the server and client.

rtc

Runtime calculations computed while the component is executing.

dataSubmitted

A pointer variable that contains the data values submitted to the callback.

oldDataSubmitted

A pointer variable that contains the original values for controls in the UX.

listInfoJSON

If the UX Component contains one or more List controls, contains an array of objects in JSON format with information about the list. Each entry in the array has the following format:

{"list":"listId","checkedRows":"comma_delimited_list_of_checked_rows"}

"list" contains the ID of the List control. If the List has a check-box select column, "checkedRows" is a comma delimited list of rows that have been checked.

You can inspect the JSON to determine what rows are checked in a List with a check-box select control. For example:

DIM listInfo AS P
listInfo = json_parse(e.listInfoJSON)

if (listInfo.size() > 0) then
    if (variable_exists("listInfo[1].checkedRows")) then
        DIM listId AS C
        DIM rows AS C
        listId = listInfo[1].list
        rows = crlf_to_comma(listInfo[1].checkedRows.dump_properties(" value"))
        ' Return JS alert displaying the list of checked rows for the first list in listInfo.
        e.javascript = "alert('Checked rows for list \'"+listId+"\' : "+rows+"');"
    end if
end if

If a list has no checked rows, the checkedRows property will be blank.

repeatingSectionNames

If the UX contains one or more repeating sections, contains a comma delimited list of container IDs for each repeating section.

repeatingSectionInfo

If the UX contains one or more repeating sections, contains a property array with one entry for each repeating section with the following properties:

activeRow

The repeating section row that had focus with the callback was made.

deletedRows

A CRLF delimited list of delete rows in the repeating section.

rowCount

The number of non-deleted rows in the repeating section.

totalRowCount

The total number of rows in the repeating section -- includes deleted rows.

fieldsInRepeating

A CRLF delimited list of fields in the repeating section.

dirtyRowsInSection

A CRLF delimited list of modified rows in the repeating section.

dirtyFieldsInSection

A CRLF delimited list of modified fields in the repeating section. Each field uses the following format:

fieldname_A5INSTANCErownum

Where fieldname is the name of the field name and rownum is the row number in the repeating section. For example, if the 'PARTNO' field for row 3 in a repeating section has been modified, the following entry will be in the dirtyFieldsInSection list:

PARTNO_A5INSTANCE3
_set

An optional variable that can be used to set the value or select properties of a control on the client. Alpha Anywhere generates the required JavaScript to send to the client to set the value or property. For example:

' Set the value of 'Lastname'
e._set.lastname.value = "Smith"

'Set the value in 3rd Repeating Section row
e._set.firstname_a5instance3.value = "Fred"

' Set the style attribute for the 'Lastname' field
e._set.lastname.style = "color: red;"

' Set the class attribute for the 'Lastname' field
e._set.lastname.className = "NewClassName"

' Set the color and font size of the 'Firstname' field
e._set.firstname.style.color = "red"
e._set.firstname.style.fontSize = "20pt"

' Set multiple values in a checkbox or dropdown:
DIM choices AS P          ' declare a pointer variable
DIM choices.value[3] AS C ' add a property called 'value'
choices.value[1] = "alpha"
choices.value[2] = "beta"
choices.value[3] = "gamma"
e._set.greekletters.value = choices

Setting style attributes preserves any existing styling. It is important to note that attribute names are case-sensitive.

Using _set to return JavaScript can have a negative impact on performance. Prefer to return JavaScript directly from your Xbasic function. EG:

DIM js AS C = ""
js = js + "{dialog.object}.setValue('LASTNAME','Smith');"
js = js + <<%js%
var ele = {dialog.object}.getPointer('FIRSTNAME'); 
if (ele) { 
    ele.style.fontSize = '20pt'; 
    ele.style.color = 'red';
}
%js%

' Return JavaScript from the callback and terminate the function:
return js
_setElement

Similar to the _set property, an optional variable that can be used to set the value or select properties of an element, such as DIV or SPAN. Alpha Anywhere generates the required JavaScript to send to the client to set the value or property. For example:

' Set the innerHTML of DIV with the id of 'DIV1' 
e._setElement.DIV1.value = "Some text"
' Set style properties of a SPAN with id of 'SPN2'
e._setElement.SPN2.style.color = "Red"

Setting style attributes preserves any existing styling. It is important to note that attribute names are case-sensitive.

Using _setElement to return JavaScript can have a negative impact on performance. Prefer to return JavaScript directly from your Xbasic function. EG:

DIM js AS C = ""
js = js + "$('DIV1').innerHTML = 'Some text';"
js = js + <<%js%
var ele = $('SPN2');
if (ele) { 
    ele.style.color = 'red';
}
%js%

' Return JavaScript from the callback and terminate the function
return js

Videos

Chunked Responses - Sending Intermediate Responses to the Client

Normally, when you make an Ajax callback from a UX component, the Xbasic function that handles the callback completes its processing and then returns Javascript to the client. In some uses cases where your Xbasic function takes a "long" time to execute, you might want to send some type of intermediate message to the client telling them that the function is still processing and perhaps letting the user know what stage the function is at.

In order to send back intermediate responses to the client while the Xbasic function is still processing, you can set the Ajax callback to allow chunked responses.

In this video we show how you can configure an Xbasic function to do chunked responses.

Download Component

2019-05-02

Checking Connectivity Before Making an Ajax callback

If the user makes an Ajax callback and there is no internet connection, the Ajax failed event will fire after the Ajax callback times out. It can take quite a few seconds before the Ajax callback times out. It would be preferable to let the user know that Ajax callbacks are not possible before they try to make a callback. Also, in disconnected mobile applications, you might want to prevent the user from tying to synchronize data if the connection is poor.

In this video, we show how this can be done.

Download Component

2021-03-28

See Also