Release Notes for Alpha Anywhere (Alpha Five Version 12)

This document describes the updates and fixes made to Alpha Anywhere since its initial release.

To see the 'What's New in V12' document (which describes all of the new features in Alpha Anywhere's initial release) please click here.

 

Please note that Alpha Anywhere patches are only available to users with a current subscription.
 

You can verify your subscription status from within Alpha Anywhere by going to Help, About, or by clicking this link shown here (https://activation.alphasoftware.com/subscriptionStatus.aspx). If you install an update for which your subscription is not entitled, you will need to uninstall the update and rollback to an older version that you are authorized to use in order to continue using Alpha Anywhere.
 

The 'Pre-Release' Build

In addition to the official updates that Alpha Software makes available from time to time (which are described in this document), we also make available our internal pre-release builds that allow you to see what features have been added and what bugs have been fixed since the last official update. The features and bug fixes in the pre-release build will be part of the next official update. To see the pre-release notes, please click here.

 

Alpha Anywhere V4.5.4.5 - Build 5221-5152 23-JUL-2018

NOTE: This build has a bug in the image upload feature. There is a fix for the bug. Download the hotfix here and then refer to the documentation for information on how to apply the hotfix.

 

Features

Web Control Panel - F2 Key - The F2 key now acts as a shortcut for the Rename command, available on the right-click menu.

 

UX Component - Action Javascript - Try/Catch Blocks - You can now wrap individual actions and the entire action in a Javascript try/catch block. To wrap an action in a try/catch block, right-click on the action and select the Wrap action in try/catch block  command. This will open an editor where you can define the code to run in the catch block. If an action is configured to use a try/catch block, the menu item will be checked.

 

 

An action can comprise several individual actions. You can also wrap the entire action in a try/catch block by checking the appropriate checkbox at the bottom of the dialog.

 

Custom APIs - Swagger Test Page - When you create a custom API using Alpha Anywhere's API creation facility, you might want to create an .a5w page where users can explore your API and test it out. In order to create an API testing page, click the New button on the Web Control Panel while the Web Components category has focus.

Then select the Swagger API Test Page option.

When your users visit this page in your published application they will be able to explore the methods exposed by your API.

 

 

 

 

UX Component - Javascript Charts - X-Axis Label Angle - You can now specify the angle for the x-axis labels. In the example below, the xaxisTextAngle property has been set to 45.

TIP When you set the xaxisTextAngle property, you may also need to set the gutterBottom property to ensure that the labels are not clipped.

 

 

 

 

UX Component - Expanding Menu - Above Menu and Below Menu HTML - You can now specify arbitrary HTML to display above and below an Expanding menu control.

 

 

 

UX Component - Summary of all defined event handlers - A new item on the Menu dropdown in the UX builder allows you to get a summary of all of the events that have been defined in the UX. This can be very helpful in a large UX with many controls because it allows you to quickly get a comprehensive view of all of the event handlers that have been defined.

To display the summary, click the Menu button and then select the Show summary of all Javascript code for event handlers menu item.

 

 

 

This will display a windows showing all of the controls on which event handlers have been defined.

 

 

 

UX Component - Action Javascript - Run a Report that is Embedded in a UX Component using a Custom Filter Action - This action now allows you to define a custom sort order in addition to the custom filter.

 

 

 

 

UX Component - PhoneGap - Offline Applications - Loading Files onto a Device - When you design an App for offline use, you may want to install files (including images, videos and SQLite databases) on the device so that these files can be accessed by your App even when there is no connection.

There are already ways in which you can load SQLite databases onto a device (using Action Javascript) and also use the client-side data cache to store data on the device, but now a new method ( {dialog.object}.phoneGapDownloadManifestFiles() ) allows you to define an arbitrary list of files that you want to install on a device.

The  {dialog.object}.phoneGapDownloadManifestFiles() method take a manifest that defines the files you want to install on the device. The manifest can either be a JSON string that specifies an array of objects (described below), or the URL of remote JSON file that specifies the manifest.

Syntax

{dialog.object}.phoneGapDownloadManifestFiles(manifest,folder,cbAllDone,optionsIn,fileSystemPart)

 

Where

Syntax for the optional optionsIn argument
 

{
    showProgress: true,
    progress: {
        color: 'green',
        width: '600px',
        progressElement: '{dialog.componentname}.V.R1.PLACEHOLDER_1'
}

 

Example

 


var cb = function(arr) { alert('File have been installed - ' + arr.length);};
 

 

//the manifest is an array of objects

//each object must have a 'url' - the url of the file

//each object must have a 'type'. types are: 'sqlite', 'folder' or 'file'.

//for 'folder' the entire folder must be zipped into a single zip file. The 'targetFolder' specifies the sub-folder

//within the target folder where the folder (containing all of the unzipped files) will be located

//for 'file', the file must not be zipped.

//for 'sqlite', the file can be zipped, or unzipped. (zipped is recommended)


array  = [
        {
            url: 'http://alphamediacapture.s3.amazonaws.com/transform/SQLiteNorthwind.zip',
            type: 'sqlite',

            version: 1
        },
        {
            url: 'http://alphamediacapture.s3.amazonaws.com/transform/sqlite3.db',
            type: 'sqlite',

            version: 1
        },
        {
            url: 'http://alphamediacapture.s3.amazonaws.com/transform/allimages.zip',
            type: 'folder',
            targetFolder: 'images',

            version: 1


        },

        {
            url: 'http://alphamediacapture.s3.amazonaws.com/transform/customer.zip',
            type: 'file',
            targetFolder: 'files',

            version: 1


        }


    ]
 

var url = 'http://alphamediacapture.s3.amazonaws.com/transform/transformManifest.json';

 

//can either specify a url that points to a manifest or the JSON manifest itself

url = array;
{dialog.object}.phoneGapDownloadManifestFiles(url,'account1',cb,opsIn)

 

 

UX Component - PhoneGap - Unzip Files - A new helper function has been added to the Alpha Anywhere Javascript library that makes it easier to work with the PhoneGap plugin that allows you to unzip files.

The function allows you to specify the file system part and folder where the source zip file located, the file system part where you want the unzipped files to be placed and optionally can call the onSuccess callback function with an array showing the files that were unzipped.

Syntax:

 

{dialog.object}.phoneGapUnzipFiles(explicitFilenameURI,filesystemSource,folderSource,zipFileName,fileSystemTarget, dirStructureTarget,onSuccess,onError,flagListUnzippedFiles)

 

Where

 

 

Web Components - Modal Windows - Tab and Sift Tab Key - You can no longer tab out of a modal window using the Tab or Shift+Tab keys.

 

UX Component - Container - Constrain Tabbing - You can now set a constraint on a container to prevent the user from tabbing out of the container using either the Tab or Shift+Tab keys. You can set the Constrain tab key property to:

 

 

TIP: Using this feature you can constrain controls in a Panel Card by wrapping all of the controls in a container.

 

PhoneGap Builder - 3rd Party Plugins - Cordova Custom URL Scheme Plugin - Added support for the Cordova Custom URL Scheme plugin. This plugin allows you to register a custom URL scheme that can be used as a link to launch your app.

When you select the Cordova Custom URL Scheme Plugin a dialog will appear to allow you to enter your custom URL scheme when you save the PhoneGap project.





The link can be added to an email, a web page or another app. As long as the app is installed on the device and the link is triggered from an email, web page or app that is being viewed or used on the device, then your app will load. You can also pass in parameters that can be used for deep linking, redirecting the app to a specific page within your app. You can also pass Base64 encoded JSON as a parameter for further processing within your app.

The plugin supports an optional handleOpenURL(url) method, that receives the URL and any parameters that were used to launch your app. This allows you to define a custom handler that can act on the path and parameters as required.

See the plugin documentation for further details and examples. cordova-plugin-customurlscheme

 

PhoneGap - Instant Update - Channels - By default, when you publish an Instant Update to your PhoneGap application, all of the users of your app will get the update as soon as they launch the app on their devices (assuming the app was designed with auto update turned on).

However, you may want to push an update to just of few users, perhaps because you are still testing a new feature. This can easily be done by specifying a channel when you publish an Instant Update.

You will need to add a user interface to your app so that a user can select what channel they are on. By default, all users are on the Production channel. But a user may change their channel to (say) the Test channel. The Javascript command that you can use to allow a user to set their channel is:
{dialog.object}.setChannel(channelName)

When you publish an Instant Update, you specify for which channel the update is intended. For example, if you publish an Instant Update to the Test channel then a user who is on the default Production channel will not get an update when they re-launch the app on their device. However, a user who has changed their channel to the Test channel will get updated when they re-launch the app. If that user later changes their channel back to the Production channel, then when that user re-launches the app, they will be automatically switched to the latest Production version.

 

 

 

Template Tester - A completely redesigned version of the Template Tester is now available. The main advantage of this new version is that all of the various editing panels (i.e. JSON data, template, css, javascript) are resizeable and can also be collapsed. Previously, each of these editing panels was on a separate tab. The new tester is more convenient to use. If you prefer the old version of the template tester you can revert to it by going to the View, Settings menu and navigating to the Preferences, TemplateTester section.

 

Bugs

Web Applications - Session Variables - Fixed a regression that was introduced in Version 4.5.4.1 enumerating session variables.

UX Components - Panel Cards - Fixed a regression that was introduced in the previous release.

 

 

 

 

Alpha Anywhere V4.5.4.4 - Build 5159-5132 22-JUN-2018

 

Bugs

 

UX Components - Panel Cards - Fixed a regression that was introduced in the previous release.

Starting Alpha Anywhere with Command Line Arguments - Fixed a regression that was introduced in the previous release.
 

 

Alpha Anywhere V4.5.4.2 - Build 5155-5130 20-JUN-2018

Bugs

Launching Alpha Anwhere from a Shortcut - A regression was introduced i the last release that broke the ability to launch Allpha Anywhere and open a named work space using a shortcut.

Application Server for IIS - Grid Component - Fixed a regression that was introduced in the last update. Grid would fail on any Ajax callback.

PhoneGap - Fixes a problem when generating an app with custom icon and splash screen.

 

Alpha Anywhere V4.5.4.1 - Build 5151-5127 18-JUN-2018

 

Videos

UX Component Cascading DropdownBoxes Using the Client-side Data Cache Cascading dropdown boxes allow you to dynamically change the choices in a child dropdown box based on the selection in the parent dropdownbox. The UX component makes it very easy to define cascading dropdownboxes. However, in applications that are designed to work offline, you cannot use the standard way of creating cascading dropdownboxes because if you are offline you cannot make the Ajax callback to populate the child dropdownboxes when the parent dropdownbox value is changed. However, you can still implement cascading dropdown boxes in offline applications by populating the dropdownboxes from data in the client-side data cache.

In this video we show how data in the client-side data cache is used to create cascading dropdownboxes.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Download files

Date added: 2018-04-30
UX Component - Map Control Computing Distance and Travel Time Between Points A common requirement in mapping applications is to compute a route (showing driving directions, distance and travel time) between points.

In this video we show how a route, defined by addresses in a List control is used to compute driving directions, distance and travel times between points on the route. The code is all generated automatically by Action Javascript.


Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Download files

Date added: 2018-04-30
SOAP Services Using the Sample WCF Service You can easily consume SOAP services from your Xbasic code. But it can be difficult to find publicly available SOAP services to test your code with. Using the sample WCF SOAP service that ships with Alpha Anywhere, you can easily create test code that shows how to consume methods in a SOAP service.

In this video we show how the sample WCF service can be used.

Watch Video

Date added: 2018-05-06
UX Component - List Control Running Totals This video shows how you can compute a column of running totals.

Watch Video

Download files

Date added: 2018-05-31
UX Component - ExpandingMenu Control Collapsing Menu When Selecting an Action When you select the action on a leaf node in an Expanding Menu control, you might want to collapse the menu so that some or all of the expanded nodes are collapsed.

In this video we show how an expanded node in an Expanding Menu control can be collapsed.

Watch Video

Download files

Date added: 2018-06-02

 

 


 




 

 

Features

Alpha Launch - New Version -  A new version (version 2.1.1) of Alpha Launch is now available in both the iOS and Android stores. With version 2.1.1, installing apps onto the device is now significantly quicker if the apps are published to Alpha Launch using the singleWithHeader option in the Download type property. With this option, all of the files that need to be installed on the device are combined into a single file which is then downloaded to the device and then unpacked on the device. It is considerably quicker to download a single large file than hundreds of smaller files.

 

Web Applications - Reload Security Information - Reload the security data for the current application - When you change the security information for an application (for example, change whether a page requires login, and if so, what groups are authorized) and you republish the application to a remote server, the new security information is not loaded immediately. It is only loaded when the security information cache is cleared (the duration of this cache is set in the Security Settings for the project). For more information on the security cache click here.

 

The a5ws_ReloadWebSecurity() function will force an immediate reload of the web security settings for the current application on a standard web server, regardless of the security cache timeout setting. The function must be run on a web page or component running on the web server. It does not reload security on an IIS server. This can be used on a maintenance page to force a reload of security after publish

The function will return .T. if successful, and .F. if running on IIS, running in Live Preview, or running in Working Preview

Syntax:

L flag = a5ws_ReloadWebSecurity( )
 

Xbasic - Using the Stripe API From Xbasic - A new genie, accessed from the right-click menu when you are editing Xbasic code, opens a genie that shows sample code for making calls to the Stripe API

 

The image below shows how the Stripe genie is accessed from the Genies... menu on the right click menu.

 

 

When you select the Stripe genie.. command the dialog shown below is shown.  The genie shows sample Xbasic code for the vast majority of the features exposed by the Stripe API.

 

 

 

Web Applications - Publishing Fonts - In some cases the server on which your application is running may not have installed a font used in one of your reports.

You can now click on the More... button on the Web Projects Control Panel and select the Create 'Fonts' folder menu command to create a folder called fonts in your Web Project. Any fonts you place in this folder will be automatically installed on the server when you print a report. This feature is especially useful on Alpha Cloud where you do not have the ability to specify what fonts each server has installed.

 

 

UX Components - Color Palettes - If a UX component uses a version 4 type style (the Alpha style is the only style currently that is a version 4 style), a new property is available in the UX builder to select a color palette.

 

 

 

Selecting a color palette is very similar to using the Customize style colors and fonts property, except that the color palette applies only to the current UX component, whereas if you use the Customize style colors and fonts property, the settings apply to every UX component in the current Web Project that uses the selected style.

 

 

When you click the smart field for the Color palette prompt the dialog that is displayed allows you to select an existing color palette, or create a new, user-defined, color palette.

 

 

When you preview a color palette or create a new color palette you will see a dialog like the one shown in the image below. This dialog allows you to set a color for each of the available color types.

 

 

 

Audit Table Feature - User Defined Field - You can now add a user defined field to the audit table to capture any additional information that you want at the time the audit table is updated. If you set the value in a special session variable called session.__audit_userfield1, the value in this variable will be written to the user defined field when the audit table is updated. If you want to store a significant amount of information in this field, consider creating a string of JSON data. The JSON data can have a large number of properties.

 

Xbasic - ShowDiff() function - The ShowDiff() function shows you a windows with the differences between data in two variables or files.

You can either choose a light theme or a dark theme (second image).

You can use the Previous and Next buttons to move from one difference to the next.

Use the black square icon on the right to change the theme.

Syntax

V =  showdiff(c varOrFile1, c varOrFile2)

 

Where

NOTE: ShowDiff() Function cannot be used in Web Application

 

 

 

Xbasic - geocode_address() Function - Now allows you to pass in an API key. If you are using Google to Geo-code addresses, Google is introducing rate limiting to the geo-coding API. You can now pass in your API key when you call this function. You can also define a project wide API key in Project Properties

 

Xbasic - SQL_Query() Function - Returns JSON data from a SQL Select statement - This function is a convenience function. It is just a wrapper around the low level Xbasic AlphaDAO commands.

 

Syntax

 

p Result = sql_query(a cnIn, c sql [, sql::arguments argsIn [, L flagPortableSQL[, L formatJSON]]]);

 

Where

 

Xbasic - A5_ink_to_png() Function - Background Color - The A5_ink_to_png() function is used to convert the Alpha Anywhere ink format (produced by the UX Ink control) to a .png image. By default, the image created has a transparent background. Now, you can specify an explicit background color.

Syntax:

function a5_ink_to_png as v (c ink ,n heightInPoints,n widthInPoints,c filename [, L flagUseViewBox [,c backgroundcolor ]])
 

 

Where

 

.Net 4.7.2 - Alpha Anywhere now installs Microsoft .Net 4.7.2. The first time you run an installer or path installer for this version there will be a significant delay while .Net 4.7.2 is installed (if it is not already installed on your machine).

 

UX Component - Expanding Menu - Set Background Color Below Menu - You can now easily set the background color of the space below the bottom an expanding menu control. This gives the expanding menu a more pleasing appearance.

 

 

 

 

In the expanding menu builder there is a new property Below menu background color.  By default, this property is set to <Same as Menu Color> which will use the Menu color defined in the previous property.

 

Alpha Launch - Publishing apps to Alpha Launch can be tricky. A new option on the Alpha Launch dialog allows you to check if your publish worked correctly. To test your publish, click the Check if files were published correctly button.

 

IMPORTANT: The publishing profile you define for Alpha Launch publishing should not use used to publish your application using the standard Publish dialog. The Alpha Launch publishing profile is for the exclusive use of Alpha Launch publishing.

 

 

 

Xbasic - Get size of JSON Array - The extension::json::ArraySize() method allows you to get the size of a JSON array, without having to first call the json_parse() function. For large JSON strings, this can result in a significant performance improvement

Syntax

n size = extension::json::ArraySize(c JsonString)

Example:

? extension::json::ArraySize("[10,20,30,40,50,60,70,80,90]")

= 9

 

Xbasic - Chunk JSON Array - The extension::json::ArrayChunked() method takes a large JSON array and breaks it into smaller chuncks

Syntax:

c JSONChuncks = extensioni::json::ArrayChunked(c json, n maximumRows, n maximumBytes, c separator)

Example:

? extension::json::ArrayChunked("[10,20,30,40,50,60,70,80,90]",3,0,crlf()+"--sep--"+crlf())
= [ 10,20,30 ]
--sep--
[ 40,50,60 ]
--sep--
[ 70,80,90 ]

 

Alpha Launch - Faster App Install - When you publish files to Alpha Launch you can now bundle the package of files that get loaded into AlphaLaunch into a single file. This makes installing apps on a device much quicker because a single file is loaded from the Alpha Launch server, rather than a large number of small files. To use this new feature, select the singleWithHeader option in the Alpha Launch Settings dialog.

NOTE: This option will only work if you have installed Alpha Launch V2.1.1 on your device.

 

 

 

JSON Path - JSON Path allows you to extract portions of a JSON string and perform certain types of simple calculations on JSON strings.

When working with XML data, there is a well known standard, called XPath, for extracting parts of the XML data. JSON Path allows for similar functionality when working with JSON data.

Xbasic now includes a new function called json_path() that allows you to perform JSON Path queries on JSON data.

You can also use JSON Path on the client side (in your Javascript code). The Javascript function is also called json_path().

IMPORTANT: The json_path() function is only available in the UX component. In addition, you must explicitly load the jsonpath system library by selecting it at the Optional system libraries property in the UX Builder if you want to use the json_path() function in your code

 

Syntax - Xbasic json_path() Function

c string = json_path(c json, c path)

Syntax - Javascript - json_path() Function

    string = json_path(jsonOrObject, path)

Where

 

 

The following sample JSON string is used in the examples below:


{
  "store": {
    "book": [
      {
        "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      {
        "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      {
        "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      {
        "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}

 

JSON PathSyntax

(NOTE: Examples are from the https://www.npmjs.com/package/JSONPath documentation)

 

$.store.book[*].author The authors of all books in the store
$..author All authors
$.store.* All things in store, which are its books (a book array) and a red bicycle (a bicycle object).
$.store..price The price of everything in the store.
$..book[2] The third book (book object)
$..book[(@.length-1)]
$..book[-1:]
The last book in order.
$..book[0,1]
$..book[:2]
The first two books
$..book[0][category,author] The categories and authors of all books
$..book[?(@.isbn)] Filter all books with an ISBN number
$..book[?(@.price<10)] Filter all books cheaper than 10
$..*[?(@property === 'price' && @ !== 8.95)] Obtain all property values of objects whose property is price and which does not equal 8.95
$ The root of the JSON object (i.e., the whole object itself)
$..* All Elements (and text) beneath root in an XML document. All members of a JSON structure beneath the root.
$.. All Elements in an XML document. All parent components of a JSON structure including root.
$..[?(@.price>19)]^ Parent of those specific items with a price greater than 19 (i.e., the store value as the parent of the bicycle and the book array as parent of an individual book)
$.store.*~ The property names of the store sub-object ("book" and "bicycle"). Useful with wildcard properties.
$.store.book[?(@path !== "$['store']['book'][0]")] All books besides that at the path pointing to the first
$..book[?(@parent.bicycle && @parent.bicycle.color === "red")].category Grabs all categories of books where the parent object of the book has a bicycle child whose color is red (i.e., all the books)
$..book.*[?(@property !== "category")] Grabs all children of "book" except for "category" ones
$..book[?(@property !== 0)] Grabs all books whose property (which, being that we are reaching inside an array, is the numeric index) is not 0
$.store.*[?(@parentProperty !== "book")] Grabs the grandchildren of store whose parent property is not book (i.e., bicycle's children, "color" and "price")
$..book.*[?(@parentProperty !== 0)] Get the property values of all book instances whereby the parent property of these values (i.e., the array index holding the book item parent object) is not 0
$..book..*@number() Get the numeric values within the book array

 

Example

 

Xbasic Example

dim path as c

'get the author for all books in the store

path = "$.store.book[*].author"

dim json as c

json = <<use the sample json string from above>>

dim result as c

result = json_path(json,path)

= [
    "Nigel Rees",
    "Evelyn Waugh",
    "Herman Melville",
    "J. R. R. Tolkien"
]

 

Javascript Example

    var path = '$.store.book[*]';

    var json = {

        //put sample json here

    }

    var result = json_path(json,path)

 

 

CURL Genie - Xbasic Template - extension::curl::RequestTemplate() Method - When you use the XBasic CURL genie (to convert a CURL command into Xbasic) a new, more concise Xbasic syntax can be generated.

The new syntax, shown in the image below in the Xbasic Template tab of the genie, takes a JSON input string to define the request.

The main advantages of the Xbasic Template over the low level Xbasic syntax (shown in the Xbasic tab of the genie) are:

In the example shown in the screenshot below, the JSON definition passed to the command defines:

 

 

 

The Xbasic Template can also be used to post multi-part form data.

 

In the screenshot shown below, the JSON defines a form property which can have form data (name "key1" and value "value1") and form data.

 

 

 

 

 

Special Placeholders

When defining the URI and the headers in the JSON passed to the extension::curl::RequestTemplate() method, there are two special placeholders that you can use:

The values for these placeholders are resolved by the specified Named Provider (see the namedResource variable in the example code below).

 

Sample Xbasic code showing how a REST API call is made to the Salesforce API.

(Assume that the authentication details for the Salesforce account have been saved in a Named Provider called salesforcetoken. )

Notice that the URI specified in the JSON string has an argument name in it (:id)

dim json as c = <<%json%
{
    "uri": "{namedresource.resourceurl}/services/data/v39.0/sobjects/Account/:id",
    "auth": {
        "bearer" : "{namedresource.access_token}"
    }
}
%json%
dim namedResource as c = "salesforcetoken"
 

'define the value of the arguments used in the URI
dim args as sql::arguments
args.add("id","0011N00001EBYRDQA5")
 

'instead of putting the account id in a sql::argument, we could have

'used a variable and referenced the variable in the URI as {accountNumber)

'instead of :id

'for example: /services/data/v39.0/sobjects/Account/{accountNumber}
 

dim vars as p
vars.accountNumber = "0011N00001EBYRDQA5"
 

dim response as extension::CurlResponse
response = extension::curl::RequestTemplate(json,namedResource,vars,args)

if response.content <> "" then

    dim json as c

    json = response.content
else

    'no response
end

 

 

 

UX Component - ViewBox Control - Data Source - REST API - The ViewBox control now has new data source type - REST API. Use this option to make a REST API call to retrieve the JSON data to be rendered in the ViewBox.

 

When you use the REST API option you can specify if the REST call is made from the server or from the client.

When you make the call from the server, the Alpha Anywhere server will make the REST API call and then return the JSON data to the browser. If you later refresh the ViewBox, an Ajax callback is made to the server, the server executes the REST API call and then returns the JSON data to the client.

When you make the call from the client, the REST call is made directly from the client using the Javascript XHR object. The Alpha Anywhere server is not involved at all.

When you make the call from the server, you can specify a URL for the REST API end point that includes placeholders that will get resolved before the call is made. You can use controls on the UX and also arguments as placeholders. For example, say you have a textbox on your UX called customerId. You might specify the URL for the REST API as:

http://www.myapi.com/customers/{customerId}

 

When the API call is made, the placeholders in the URL are resolved. So, for example, if at the time the ViewBox is refreshed, the customerId control has a value of CUST_01, the URL for API call will be:

http://www.myapi.com/customers/CUST_01

 

Argument values are represented in the URL using :argument_name. For example, assume you have an Argument called CUSTOMER_ID. You could specify this URL for the API endpoint:

http://www.myapi.com/customers/:CUSTOMER_ID

 

In some cases, the API endpoint you call will be authenticated. For example, many API endpoints require an oAuth authentication or a "service account" login. You can specify the name of a Named Provider (defined by going to the Tools menu when the Web Control Panel has focus, and selecting Tools, Named Providers, or by opening the Project Properties dialog).

In the case where the call is made from the server,  you can optionally specify an Xbasic function to post-process the JSON data that is returned by the REST API call before the data is returned to the client. In the case where the call is made from the client, you can optionally specify Javascript code to post-process the data before the ViewBox is populated.

In the case where the API call is made from the client, the URL is defined by Javascript code that must return the URL. This allows you to easily construct URLs that are dynamically computed, based on data in the component.

 

 

UX Component - ViewBox Control - Data Source - Custom - The ViewBox control now has a new data source type - Custom. When you select the Custom option you can specify the name of an Xbasic function. This function should return the JSON data that the ViewBox will render.

An example of where the Custom option could be used is if the data that you want to show in your ViewBox is returned from a SOAP service request, or you need to aggregate data from multiple data sources.

 

UX Component - List Control - <listObject>.removeRows() Method - Animation - You can now turn on animation when you remove rows from a List control using the .removeRows() method.

Syntax

<listObject>.removeRows([rowsToDelete [,flagAnimate]])

Where

 

 

UX Component - httpFetch() Method - A new method has been added to the UX component to fetch data from a remote URL.

Syntax:

{dialog.object}.httpFetch(url,onSuccess,onError[,headers])

 

Where headers is an optional array that allows you to set custom headers for the request. The headers array is an array of objects. Each object has a name and value property.

For example:

var headers = [];
headers.push( {

    name: 'Authorization',

    value: 'Bearer my_access_token_value_goes_here'

});

 

The onSuccess callback function get called when the data are available.

Example:

var url = 'http://some_remote_url'
var cb = function(data) { console.log(data)}
var fail = function() { alert('request failed');}
{dialog.object}.httpFetch(url,cb,fail)

 

Template Tester - MDI Window - The Template Tester (accessed from the Tools menu when the Web Control Panel has focus) is now a MDI window rather than a modeless window. This makes it easier to keep the Template Tester window open while you are working on other tasks.

Template Tester - Default Template - The Template Tester now has a new link on the Template pane to generate a default template from the JSON data. In cases where the JSON data is very complex, this can give you a quick start on building a new template. The default template can be generated in one of two ways: compact, or fully expanded.  The 'compact' option will use containers (e.g. {orders}....{/orders}) for arrays, but not objects. The 'fully expanded' option will use containers for both arrays and objects and it results in a larger template.

 

Alpha Anywhere Server for IIS - Performance Improvements - Session State Storage -

All session state providers have a new option to specify storage. A button is available in the new publish profile genie
 




and a new option is available in a publish profile's property sheet "Session State Storage Type" :



Session State Storage Type defines where session files are stored.

There are 2 options:


When "Storage Connection String" is selected there will be an additional prompt for the storage connection string.



When the storage connection string is of type "Disk" there will also be a "Storage Lifetime" and "Storage Scope" prompt.

 

Alpha Anywhere Server for IIS -  Redis Installed as a Service - The Application Server for IIS installer will now install Redis as a Windows service. This service will be installed for Manual start. If an application uses Redis for session state provider, this service can be set to Automatic start up and started up to provide a Redis instance. The redis.config for the service is located in C:\ProgramData\Alpha Software\Redis. See (https://www.alphasoftware.com/documentation/pages/Guides/IIS/ConfigureProviders/ProviderConfiguration.html#section2_configureRedis) for understanding the options in the redis.config file.
 

SQLite Database - A new menu option on the Tools menu (when the Web Control Panel has focus) allows you to create an SQL database and populate the database with data. After the SQLite database has been created, it can optionally be uploaded to Amazon S3. This makes it easy for mobile applications to download the database and store it on a device.

To select the option select Tools, More.., Create SQLite Database

 

Xbasic - High Precision Numeric Calculation - When doing numeric calculations with Xbasic there can sometimes be a loss of precision because internally Xbasic uses floating point numbers. A new class is available in Xbasic for high precision calculations. When using this new class, all input numbers and output results are variables of type character (not number).

For example:


 


? MathUtil::Decimal::Add("1.20","2.30")
= "3.50"
? MathUtil::Decimal::Subtract("1.20","2.30")
= "-1.10"
? MathUtil::Decimal::Multiply("1.20","2.30")
= "2.7600"

? MathUtil::Decimal::Divide("1.20","2.30")
= "0.5217391304347826086956521739"

? MathUtil::Decimal::Compare("1.20","2.30")
= -1


 

Web Applications - Publish - Done Message - After a web project is published, a dialog can now be shown to confirm that publishing was completed. You can toggle whether this dialog should appear or not by opening the Project Properties dialog from the Web Control Panel and selecting the Design-time tab.

NOTE: By default, this dialog is turned off. You must go to Project Properties, Design-time Settings to turn it on.

 

NOTE: Alpha Anywhere also displays a dialog after publishing files as shown below. This dialog can be turned on/off by going to the View, Settings menu and navigating to the Preferences, Web Publishing section. The setting to show or hide this dialog is system wide, while the settings for the new Publish Complete dialog are just for the current Web Project.


 

 

 

UX Component - PhoneGap - Instant Update - First-time Run Message - The first time you load a PhoneGap app (built using the Instant Update feature) on a device the app files must be unzipped and stored in a folder on the device. On most newer devices, this process happens quite quickly. However, on some older Android devices, it can take some time to unzip the files. It can appear to the user that the app is not responding. Therefore, you can now display a message to the user when the app is unzipping files for first time use. The message should tell users that this is a one-time delay and that they must wait until the files have been prepared.

 

 

Xbasic - A5InstanceCount Function - Returns the number of instances of Alpha Anywhere that are running.

 

Syntax:

n count = A5InstanceCount()

 

 

Runtime Applications - Control Panel - In most Runtime Applications, the Control Panel is hidden from the user. However, in some Runtime Applications, the user is allowed (by the designer of the Runtime Application) to get access to the Control Panel. You can now control which panes in the Control Panel should be visible in a Runtime Application

To set the visible panels, select the File, Workspace Properties menu option.

 

 

Documentation - Notable new Articles  - Several new notable articles have been added to the documentation. These articles are highlighted here:

 

 

Consuming SOAP Services - Sample Service - Alpha Anywhere now has a sample WCF service that you can host locally. This makes it very easy to test how to consume a SOAP service from Xbasic.

 

Watch Video
 

You can automatically install and run the sample, locally hosted, service when you create a new Web Reference client at the Web Control Panel, as documented in the steps below:

 

 

1. Click on the New button when the Web Services category is selected.

 

 

2. Click the Create a new definition to consume a SOAP web service button.

 

 

3. Select the Sample WCF Service item from the dropdown when you click on the Insert Sample hyperlink.

 

 

 

 

UX And Grid Components - Friendly Dates - String Customization  - You can now customize the strings used to display 'friendly dates' (e.g. a friendly date might display 'today' by default, but you might want to customize this so that it displays in the user's language of choice).

You can now customize all of the strings used in friendly dates by setting the Friendly dates customization property. You can use language and text dictionary tags in the customized strings.

 

 

 

UX Component - List Control - Fields - Security Groups and Server-side Show/Hide Expressions - When you define a List control, the List Builder allows you to specify security groups and server-side show/hide expressions for any of the fields in your List's data source.

A clarification has been added in the builder explaining that these settings only apply to fields used in a Column List layout. They do not apply in a Freeform layout. Furthermore, these settings only control whether a particular column in the List layout should be shown or not -- they do not affect the data that are sent from the server to the browser. (So, for example, if you have set a security setting on (say) the 'salary' column, the 'salary' column will be hidden in the List, but the List data that is sent from the server to the browser will still include the salary data).

If the List is based on a SQL query, then if you have defined security groups or show/hide expressions for any field in the List data source, when you close the List Builder a new dialog (shown in the image below) will appear asking if you want to copy your security and show/hide settings to the Data Source tab. The advantage of doing this is that the security and show/hide will be applied at the query level (meaning that in the above example, the salary data will not be included in the List data that is sent from the server to the browser).

 

 

 

 

UX Component - PhoneGap - iPhoneX - Sample Template - Styling a PhoneGap application so that it looks good on an iPhoneX can be tricky. A new sample template for UX components is available to help you get you styling right.

When you create a new UX select the PhoneGap - iPhone X Styling template.

 

 

 

PhoneGap  iPhone X - Important information about styling an iPhone X application so that it appears full screen has been added to the documentation. The article can be accessed from this link. If you are building PhoneGap apps for iPhone X, this article is essential reading.

 

PhoneGap Builder - Hot Topics Link - The PhoneGap builder now has a new hyperlink that opens the 'Hot Topics' documentation in the Help System. The PhoneGap ecosystem is in constant flux. As Adobe updates the PhoneGap build service from time time time, things that used to work may not work the same way or plugins that used to work may no longer be working. The Hot Topics document in the Help System helps you stay on top of the changes to PhoneGap and alerts you to things you might need to do in your PhoneGap projects.

 

 

 

 

UX Component - Bind Controls Dialog - The Bind Controls to Fields dialog is now easier to work with (especially for UX components that bind a large number of fields) because the dialog now allows you to filter and sort the data shown in the table.

 

 

 

UX Component - Map Control - Action Javascript - Compute Distance and Travel Time Between Points - A new action type has been added to the Google Maps Methods action. The action is called Get distance and travel time between points. It takes an array of addresses (either strings or longitude/latitude values) and computes the distance and travel time between each set of points in the array.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

 

 

The builder for the action is shown below. You can either pass in a start and end address or multiple addresses.  In the case where you select MultipleAddresses you must specify the name of a Javascript function that will return an array of addresses. For example, if your function returns an array with these addresses:

 

['address1','address2','address3']

 

the action will compute the distance and travel time between:

The action is asynchronous, so when all values have been computed, a callback function is called. You can specify the Javascript run run in the callback function in the onReady Javascript property.

In your Javascript you can reference an array called data that has an item for each address pair. Each item in the array has these properties:

 

In addition you can reference these variables:

 

 

Control Panel - Contains optimizations to improve the way in which the Control Panel is rendered

 

UX Component - PhoneGap - Instant Update - Quick Build - If your PhoneGap project has turned on the Instant Update feature, a new button appears on the Web Projects Control Panel toolbar that allows you to quickly build an Instant Update without having to bring up the PhoneGap Genie. All modal dialogs normally displayed when an Instant Update is built are suppressed.

 

UX Component - Action Javascript - Map Control - Plot Route - A new action in Action Javascript - Google Map Method makes it easy to plot a route on a map and get directions (either driving, walking or bicycling).

 

 

 

The builder for the new Plot route action is shown below:

 

 

 

The Type property can either be StartAndEndAddress or MultipleAddress. If you select StartAndEndAddress you can either enter address for the start and end (e.g. '36 Bigelow St. Cambridge MA') or latitude/longitude values (comma delimited (e.g. 42.3685632,-71.1045822). You can also specify the name of a Javascript function to return the start and end address. To use a Javascript function, specify the address as:

javascript:name_of_your_function

 

If you select MultipleAddress option, then you must specify the name of a Javascript function. This function must return an array of addresses. Each address in the array can either be an address or a lat/lng value (comma delimited).

 

 

 

Bugs

Reports - PDF - Watermark - Fixed an issue where settings for PDF watermarks were not being honored under certain conditions.

fedex_delivery_status() Function - Fixed this function.

 

Grid Component - Search Part - Checkbox - Fixed a regression where a search using a checkbox control combined selected options using AND rather than OR.

SQL Server Reporting Services Reports - Multi-select Parameters - Numeric Stored Value - If a SSRS report had a multi-select parameter that had a numeric stored value (i.e. the parameter displayed a list of string values, but each string value had a numeric stored value), the report could not be displayed by Alpha Anywhere.

SQL Auditing - The SQL Audit feature was not correctly inserting the name of the Grid that was used to edit a table when the component was run in live mode. In Working Preview, it worked correctly. Also, the audit feature was not inserting the connection string into the Audit Table. You will need to recreate the Audit Table to get the fix for the connection string.

 

 

 

Alpha Anywhere V4.5.4 - Build 5028-5088 19-APR-2018

 

Videos

Auditing Auditing Table Edits In many applications it is desirable to keep track of every edit made to a SQL table so you can know what fields were changed, who made the edit and when the edit was made. This is often achieved by added update, insert and delete triggers to the SQL database. But in cases where it is not possible to modify the database, you can use the built-in auditing feature in Alpha Anywhere.

In this video we show how the auditing feature is set up and used.

Watch Video

In cases where updates to SQL tables are made in your own Xbasic code (as opposed to from UX and Grid components), it is necessary to manually update the audit log. In this video we show how this is done.

Watch Video - Part 1
Watch Video - Part 2


Date added: 2018-15-06

 

 

Features

 

Auditing  - You can now enable an auditing feature to keep track of all edits made to SQL tables in an application. Information about each Insert, Update and Delete is kept in the Audit table. This table keeps track of the type of edit, the user id of the person making the edit, the name of table that was edited, and the old and new value of each field that was edited.

Watch Video

 

To turn on the Auditing feature, go to the Project Properties dialog in your Web Project (click the Project Properties button when the Web Control Panel has focus) and then check the Keep track of edits to tables made through Grid and UX components property.

 

 

Once you do this, you will be able to specify the connection string to the database where the Audit table is stored. You can either map an existing table, or create a new table.

 

 

By default, the User Id of the user who made the edit to a table is obtained from the Alpha Anywhere security framework (by evaluating the context.security.currentUser expression). However, if you are not using the Alpha Anywhere security framework, you can define a custom expression to get the user id of the person who made the edit.

 

In the case where you are making updates to SQL tables in your own Xbasic code, you will need to manually update the audit log table. There are two helper function in Xbasic to make this easy:

 

For example, the following code updates a table and also updates the audit log

dim cn as sql::Connection

cn.open("::Name::Northwind")

dim args as sql::arguments

args.add("primaryKey","ALFKI")

args.add("title","Manager")


dim sql as c
sql = "update Customers set title = :title where CustomerID = :primaryKey"

'capture the BEFORE update values
dim dataJson as c
dataJson = a5Helper_getAuditInfoFromSQLStatement(cn,sql,args.xml)

flag = cn.Execute(sql,args)

'write to the auditing table
a5Helper_writeToAuditingLog(cn,"Update",dataJson,"CustomerID","ALFKI")
 

TIP: The Audit table can grow to be very large in a large application used by many people. You might want to implement a strategy to purge old records from the audit table from time to time.

Alpha Anywhere Server for IIS - Redis is now an option for the Session State Provider in a publish profile.
 




The configuration settings are as follows:
 


JIT session locking can also be set.

The option will only appear on the profile property sheet.

 





It is also only available for the Redis provider.

The SecurityConfiguration object has a new property JitSessionLock that when set to true and the new AddSessionStateProviderRedis() is called, will configure to use the JIT session state wrapper with the Redis session state provider.

 

UX Component - Action Javascript - PhoneGap - TouchID/FaceID Action - A new action in Action Javascript allows you to easily use features in the PhoneGap TouchID plugin.

 

Bugs

UX Component - Reports - CurrentListFilter() - Fixed an issue when using the special CurrentListFilter() function an a report filter if the List was a parent of another List with pre-fetched data.

UX Component - Detail View - PhoneGap - Image Capture for List Detai View - onImageCapture Event - Was not firing if the capture method was set to PhoneGap.

Reports - Report Server - Images - PDF Reports - If you have a report with images in the data, then when printing the report to PDF from a web application, the images did not appear in the PDF. This problem does not happen if you turn off the Report Server (from the Project Properties dialog). The problem also does not affect the IIS server, or Alpha Cloud as neither of these use the Report Server. This issue is now fixed.

Web Applications -- IIS Server - Workspace reports, labels and letters are now all allowed if component security if turned off.

TabbedUI - Running a TabbedUI in build 5007 that had been created in an older build caused a Javascript error in certain cases.

 

 

Alpha Anywhere V4.5.3 - Build 5009-5081 10-APR-2018

Web Applications -- IIS Server - Workspace reports, labels and letters are now all allowed if component security if turned off.

TabbedUI - Running a TabbedUI in build 5007 that had been created in an older build caused a Javascript error in certain cases.

Alpha Anywhere V4.5.3 - Build 5007-5081 09-APR-2018

 

Videos

UX Component - PhoneGap Using the Instant Update Feature in a PhoneGap Application After you have created a PhoneGap application from a UX component, if you subsequently want to update the application you need to go through the entire release cycle again (i.e. submit to PhoneGap Build, then submit to the appropriate App Store). However, if you enable the Instant Update feature when you build your application in the first place, you can make certain types of updates to your application without having to go through the release cycle again.

Instant Update can be used as long as you are not changing the PhoneGap plugins used by your application, or the splash screens, etc. You can perform an Instant Update on an application as long as the changes to the application are limited to changes in the application's UX component.

In this video we show how the Instant Update feature operates.

Watch Video - Part 1
Watch Video - Part 2

Date added: 2017-12-24
Grid Component - Alphabet Button Search Adding Bubble Help with Record Counts to Buttons in Alphabet Button Search Bar The Alphabet Button search bar in a grid is a convenient way for searching for all records where a field starts with a particular letter. It can be useful for the user to know how many records are in each group before they actually press the button to execute the query.

In this video we show how bubble help is added to each button in the Alphabet button search bar. When the user hovers the mouse over the button, the bubble help shows how many records are in the group.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Download component

Date added: 2017-12-31
Reports Alternating Background Colors for Records in the Detail Section It is common in reports to print alternating rows in the report's Detail section with different background colors.

This video shows how this is done.

Watch Video

Date added: 2018-02-01
UX and Grid Components Display Date and DateTime Values using Formatted Text Date and datetime values are easier to comprehend when they are formatted in a 'friendly' manner (e.g. today, in 1 hour, tomorrow).

In this video we show how you can display date and datetime values using 'friendly text' in a Grid and UX component.

Watch Video

Date added: 2018-02-04
UX Component ViewBox - Client Side Reporting Using the ViewBox control, it is possible to create highly stylized client-side reports. In this video we build on a previous view in which a sample Invoice report is created. The video shows how you can configure the report to allow the invoice line-items to be collapsed (i.e. hidden) or expanded. The video also shows how you can add a button to the report to generate a PDF file for the report.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Date added: 2018-02-10
UX Component Mobile Date Picker In a mobile app, the standard date picker control that the UX uses may be too big for the screen. In this case, it might be desirable to use a date picker that is more tuned to a mobile application, such as a control that uses Spin Lists to select the month, day and year.

In this video we show how to use Spin List controls to edit the value in a date field.

Watch Video

Download component

Date added: 2018-02-23
UX Component - List Control Displaying Friendly Dates in a List Control The data picker control allows you to display dates in a friendly format (i.e. today if the date is today's date).

In this video we show how date values displayed in a List control can be displayed in a friendly format.

Watch Video

Download component

Date added: 2018-02-23
UX Component - ViewBox Control
Using a ViewBox to Create Nice Looking Email Messages The ViewBox component can create beautifully styled HTML by merging data into a template to create a customized, styled HTML document. You might want to email the contents of the ViewBox to someone as an HTML message.

In this video we show how a ViewBox can be used to create some nice looking HTML output (by merging JSON data for a customer's order into an HTML template) and then sending the resulting output as an HTML email.

Watch Video - Part 1
Watch Video - Part 1

Download component

Date added: 2018-03-02
UX Component - ControlBar Control Scrolling disclosure menus A common practice when building ControlBars is to have a button on a ControlBar that displays a menu that slides in from the left or right. The menu can be implemented using a List (which is inherently scrollable), but can also be implemented using a disclosure (which is a much simply solution).

In this video we show how the disclose menu can be made to scroll.

Watch Video

Date added: 2018-03-27
Salesforce Creating a Salesforce Connected Application Before you can work with Salesforce data in an Alpha Anywhere application, you must first define a new Connected Application in your Salesforce account and a Named Resource in your Alpha Anywhere Web Project.

This video walks through the process of creating a Salesforce Connected Application

Watch Video

Date added: 2018-04-06
Salesforce Creating a Named Resource Provider Before you can work with Salesforce data in an Alpha Anywhere application, you must first define a new Connected Application in your Salesforce account and a Named Resource in your Alpha Anywhere Web Project.

This video walks through the process of creating a new Named Resource Provider in your Alpha Anywhere web project.

Watch Video - Part 1
Watch Video - Part 2


Date added: 2018-04-06
Salesforce Making REST API Calls Then SalesforceAPIRequest() function makes it easy to make REST API requests to the Salesforce API. You can either make a request directly against an endpoint documented in the Salesforce API documentation, or you can use the Salesforce SQL like query language, SOQL, to execute queries.

In this video we show both uses of the SaleforceAPIRequest() function.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Date added: 2018-04-06
Salesforce Creating a Connection String You can create a Salesforce connection string (just as you create connection strings to point to SQL databases) that then allows you to treat Salesforce as a data source for a component, or a control.

In this video we show how a Salesforce connection string can be defined and then used to create a Grid component.
Watch Video - Part 1
Watch Video - Part 2

Date added: 2018-04-06
Salesforce Building a UX Component That Uses the Salesforce API In this video we show how a UX component can be built to display Salesforce data. The UX component does a query to retrieve the a list of accounts from Salesforce and it displays the result in a List control. When the user clicks on a row in the List, details for the selected account are shown by making another API request to Salesforce.


Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Download component

Date added: 2018-04-06
Creating a REST API Creating a simple REST API You can create REST APIs in Alpha Anywhere to expose functionality defined in an Xbasic class or a Node API.

In this video we show how a simple API is defined.

Watch Video - Part 1
Watch Video - Part 2

Date added: 2018-04-06
Creating a REST API Passing parameters to a method In the previous video we showed how to expose a very simple method in a REST API. The method did not take any arguments. Typically most of the methods you expose in your API will take arguments. These arguments can be supplied to the method being called in various ways (as part of the request URL, in query parameters, in the request header, or in a POST body).

In this video we show how a method that takes a single parameter can be exposed in a REST API.

Watch Video

Date added: 2018-04-06
Creating a REST API Authenticating a method in a REST API When you create a REST API that exposes one or more methods, you might want to require that some (or all) of the methods exposed by the API should require some type of authentication before the call can be made.

In this video we show how to require authentication for certain methods in your API.

Watch Video - Part 1
Watch Video - Part 2

Date added: 2018-04-06
Creating a REST API Auditing an API You can use the audit feature when you create a REST API to keep track information such as how often a particular endpoint is called, how long each method takes to execute. You might want this information so you can implement some type of rate limiting for you API to ensure that it is not being abused.

In this video we show how you can define methods to audit the use of your API.

Watch Video

Date added: 2018-04-06
Creating a REST API Defining the Encoding for the Body Data A common use case for an API is to create a new record in a database or to update an existing record in a database. In these cases, the request will typically be a POST and the data for the new or updated record will be in the request body. The data in the body can either be FORM or JSON encoded.

Watch Video

In this video we will show the difference between FORM and JSON encoding the body data.

Date added: 2018-04-06
Creating a REST API Returning Complex JSON Data In this video we show how to create a REST API that returns complex JSON data for a customer. The API will return data about a particular customer, including all of the orders placed by that customer, and for each order, all of the line items in that order. The data will come from querying the sample Northwind database. The video shows an example of the type of complex data that a REST API is often designed to return.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Download files

Date added: 2018-04-06
Creating a REST API Importing a Swagger Definition When you create a REST API you can either start by defining an Xbasic Class that defines the methods you want to expose in your API, or you can start by importing a Swagger definition for the API. Swagger is an open source standard for describing REST APIs. When you import a Swagger API definition, Alpha Anywhere will create a stub Xbasic class that you can then edit.

In this video we show how you can import a Swagger definition.

Watch Video

Date added: 2018-04-06

 

 

Breaking Changes

Web Applications - Active Directory  - As a result of changes in the way Active Directory authentication is now implemented, certain applications may need to be reconfigured. If an application uses Forms Based Active Directory for authentication and authorization (i.e. for users and groups) the Active Directory Configuration in the publish profile may need to be updated if the users are defined in one organizational unit and roles are defined in a different organizational units.

The Active Directory Configuration dialog now has an additional prompt for the organizational unit that specifies the groups used by the application. The input value is the distinguished name of the organizational unit. This prompt can be set to "All Organization Units" if groups are in the same hierarchy as specified in the LDAP connection string.



Given this Active Directory structure:


 

Company Domain (Domain)
    Users (Users)
        User1
        User2
        User3
    Car Division (OU)
        CarUser1 (User)
        CarUser2 (User)
        CarUser3 (User)
    House Division (OU)
    Application Division (OU)
        Group1 (Group)

            User1

            CarUser1
        Group2 (Group)

            CarUser2
        Group3 (Group)

            User1


 

And this LDAP connection string:

LDAP://ad.company.com/CN=Users,DC=ad,DC=company,DC=com

 

And a setting in the Organizational Unit for groups prompt of:

OU=Application Division,DC=ad,DC=company,DC=com

 

Then, anyone in Active Directory can login, but only users in an "Application Division" group (i.e. Group1, Group2, Group3) will have access to protected pages.


Next, assume the following LDAP connection string:


LDAP://ad.company.com/OU=Car Division,DC=ad,DC=company,DC=com

 

And assume that the setting for the Organizational Unit for groups  prompt is:


OU=Application Division,DC=ad,DC=company,DC=com
 

In this case, only users in the Car Division OU will be able to login. Only the users that are assigned to an "Application Division" group will have access to protected pages.

This change affects both the Standard Application Server and the Application Server for IIS.

 

 

Application Server - Cookieless Sessions - Support for cookieless session tracking has been removed from the Classic Application Server. This eliminates the small possibility that previously existed of "session hijacking".  Your application users must now support cookies in order to use sessions with the Classic Application Server.

 

 

Features

REST API - Creating - You can now create an publish REST APIs. Alpha Anywhere has always had the ability to consume REST APIs, but now you can also publish your own REST APIs.

For details on how to create and publish a REST API, click here.

Salesforce - Extensive support for working with Salesforce data has been added to the Alpha Anywhere. For complete details on how you can work with Salesforce data in an Alpha Anywhere application, click here.

 

PhoneGap Build - Instant Update - The Instant Update feature allows you to update a PhoneGap App that has already been installed on a user's device without needing to submit the App to the PhoneGap Build service after you have made changes to the App and without having to re-submit the App to the App stores.

As soon as the user launches the App on their mobile device, the App will be instantly updated to the latest version of the App.

 

Watch Video - Part 1
Watch Video - Part 2
 

The first time you create a PhoneGap App from a UX component, you are creating a Baseline for this application. The Baseline App must be submitted to the PhoneGap Build service, and must then be submitted to the appropriate App Stores.

After you make changes to the App, the PhoneGap genie will prompt if you want to do an Update build, a new BaseLine build, or Roll-back to a previous update.

NOTE: You can only use the Instant Update feature if you do not need to change any of the PhoneGap plugins used in your App. If you need to change PhoneGap plugins, you will need to create a new Baseline application.

If you select to do an Update build, the PhoneGap genie will determine which files in your project have changed (relative to the Baseline build) and will upload a changes file to a server (either an Alpha Software Amazon S3 bucket, or your own Amazon S3 bucket). When a user launches the App on their device, the App will automatically check if a new version is available, and it will instantly update itself to the new version.

If you release an Update to your App, and you find that this new version has introduced a bug, you can roll back to a prior version. When the user launches the App on their device, the App will instantly be downgraded to the specified previously released version.

To turn on the Instant Update feature, set the Enable Instant Update property to Yes.

 

Once you have enabled Instant Update the Instant update settings property is revealed

 

 

 

The options in this dialog are:

                    The current installed version number (shown when the App is launched)

                    App is running latest version message (if no update to the App is found)

                    App was updated message (if an update was found)

                    In Verbose mode, the user-defined After update message will also be shown.

                    Fatal errors are always shown.

 

 

How to Configure A Private S3 Bucket

The S3 bucket you specify must have a CORS policy set. Click the CORS Help hyperlink on the Instant Update Settings dialog for more information on CORS.

You will also need to set a bucket policy to set the objects in the bucket to allow public read. The policy can be set in the Amazon AWS management console and it will look something like this:

{
    "Id": "Policy1513279106848",
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1513279094040",
            "Action": [
                "s3:GetObject"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::your-bucket-name/*",
            "Principal": "*"
        }
    ]
}			
			
			
			

UX Component - PhoneGap Applications - {dialog.object}.instantUpdateCheckForUpdate() Method - This method allows you check if an update is available in a PhoneGap application that was build with the Instant Update feature enabled. Since this is an asynchronous operation, you need to provide the JavaScript success and the error callback functions.

If a result is returned within a 5 second time-frame, the successCallback is called and passed an object with a result property that will be either true or false. If true, an update is available. If a timeout or any other error occurs the error callback is passed an error object or a string, depending on the error.

This method can be useful if you have turned off auto updates and want to programmatically check if an update is available.

Syntax:

{dialog.object}.instantUpdateCheckForUpdate(_successCallbackFunction,_errorCallbackFunction);

 

Where

_successCallbackFunction - function to call if there is an update available

_errorCallbackFunction - function to call if there was an error checking for an update.

 

UX Component - PhoneGap - Instant Update - By default, if you build a PhoneGap App and you turn on the Instant Update feature, every time the App is launched in a device, the App will check if a new version is available. You can turn this default behavior off.

When you define your PhoneGap project, the Instant Update Settings dialog has a property called Automatically check for update when App is started. If you uncheck this property, then when the App is started, it will not automatically check for a new version.

 

 

 

 

Use the {dialog.object}.instantUpdateRefresh() method to force a check for a new version at runtime.

You can toggle this setting on or off at run-time using this method: {dialog.object}.instantUpdateUseAutoUpdate(true/false);
 

 

UX Component - PhoneGap Applications - Instant Update - URL For AJAX Callbacks - When creating an Instant Update to an existing baseline application, you can now change the URL for Ajax callbacks by checking the Change AJAX URL property in the image shown below.

When you press the OK button, the Genie will prompt for a new AJAX callback URL.

 

The AJAX callback URL is set in the PhoneGap builder when you create he baseline version of your application. When you create an update you might want to change this URL so that users who are still running an older version of your APP are still making callbacks to the original location, while users who are running the latest version of your App will make callbacks to a new location.

Another reason why you may want to change the URL for AJAX callbacks is that you simply want to move the location where your App is hosted. For example, you might be migrating from on premises deployment to deploying in the Alpha Cloud.

IMPORTANT: If you change the URL for AJAX callbacks be sure to also publish your App to that location!

 

 

UX Component - PhoneGap Applications - Instant Update - Version Numbers - When you create an Instant Update to a PhoneGap Application, each update is automatically give an internal version number. The internal version number is an integer that automatically increments each time a new Instant Update is created.

Now, you can also define your own version number for each Instant Update. The version number can use any numbering pattern that you want. (The Internal Version Number will also still be generated). In addition you can define a description for the Instant Update.

Your version number and description will make it easier if you need to roll back to a previous version to select the version to which you want to roll back.

 

 

UX Component - PhoneGap Applications - {dialog.object}.instantUpdateRefresh() Method - This method allows you to check for a new Instant Update version of an application without having to exit the App on the device and then re-launch it.

The method is only available in a PhoneGap application that was build with the Instant Update feature enabled.

Normally, after you publish an Instant Update to a PhoneGap application, users will not get the new version until they re-launch the application on their devices.

Using this method, you can get a new version of the application without have to exit and re-launch the application.

Syntax:

{dialog.object}.instantUpdateRefresh()

 

 

Xbasic - JSON_normalize() Function - Takes an array of JSON objects and "normalizes" the data to create an hierarchical JSON object.

For example, consider the following "un-normalized" JSON array:

 

[
{"name" : "john", "state" : "MA", "city" : "boston"},
{"name" : "fred", "state" : "MA", "city" : "boston"},
{"name" : "liz", "state" : "MA", "city" : "springfield"},
{"name" : "jill", "state" : "NY", "city" : "albany"},
{"name" : "sid", "state" : "NY", "city" : "manhatten"},
{"name" : "tammy", "state" : "NY", "city" : "manhatten"},
{"name" : "fran", "state" : "RI", "city" : "providence"},
{"name" : "tess", "state" : "RI", "city" : "providence"}
]

 

Notice that the "state" and "city" properties are duplicated in each array item.

You can use the JSON_normalize() function to produce the following "normalized" JSON:

 

			
[
    {
        "state": "MA",
        "_list_1": [
            {
                "city": "boston",
                "_list_2": [
                    {
                        "name": "john"
                    },
                    {
                        "name": "fred"
                    }
                ]
            },
            {
                "city": "springfield",
                "_list_2": [
                    {
                        "name": "liz"
                    }
                ]
            }
        ]
    },
    {
        "state": "NY",
        "_list_1": [
            {
                "city": "albany",
                "_list_2": [
                    {
                        "name": "jill"
                    }
                ]
            },
            {
                "city": "manhatten",
                "_list_2": [
                    {
                        "name": "sid"
                    },
                    {
                        "name": "tammy"
                    }
                ]
            }
        ]
    },
    {
        "state": "RI",
        "_list_1": [
            {
                "city": "providence",
                "_list_2": [
                    {
                        "name": "fran"
                    },
                    {
                        "name": "tess"
                    }
                ]
            }
        ]
    }
]
			
			

Syntax:

c jsonOut = json_normalize(c jsonIn, c groupingOptions)

 

Where:

In the above example, the command used to produce the normalized JSON is:

json_normalize(jsonin,"state,city")

 

This indicates that the first level of grouping is on the "state" property, and the second level of grouping is on the "city" property.

 

NOTE: The json_normalize() function is the reverse of the json_flatten() function.

 

UX Component - ControlBar - Disclosure Type - Template - A new type of ControlBar disclosure can now be created. The Template type allows you to create arbitrary HTML and inject placeholders for ControlBar items into the HTML.

Watch Video

For example, assume you have defined these ControlBar items: Button1, Button2 and Button3.

You can inject these controls into the HTML for the template using these placeholders: [Button1], [Button2] and [Button3].

The Template type is similar to the HTML disclosure type in that they both take an HTML template. There are however significant differences. The Template type is regenerated every time the disclosure is opened and you can inject ControlBar items into the template. The contents of the disclosure can be scrolled.

The HTML type is rendered once at the time the ControlBar is instantiated and you cannot inject ControlBar items into the HTML. The contents of the disclosure cannot be scrolled.

 

 

 

UX and Grid Components - Action Javascript - Open a Grid and Open a UX Actions - Ajax Failed Message - The actions to open a child UX or Grid have always allows you to specify a value for the Ajax failed message.  This message is displayed in the case of a failed Ajax callback (i.e. the server does not respond). Now you can execute arbitrary Javascript when the Ajax callback fails by specifying the Ajax failed message as

javascript:name_of_your_javascript_function

 

UX Component - Sample Template - MobileApp_HOST_UX_with_multiple_linked_child_UX_components - When you create  new UX Component, a new template is available.

This template shows a possible design solution for the use case where you have a parent table (e.g. customers) and you want to be able to display/edit an arbitrary number of tables related to a particular customer. For example, each customer can have multiple Order, Payments, Credits, Returns, Notes, etc.

The sample UX component shown in this template is analogous in concept to a Grid based on the Customer table with a row expander showing grids for each of the related child tables.

 

 

UX and Grid Component - Auto-suggest - Speed Improvement - By default the auto-suggest used the Upper() function in the SQL select statement to force the query to be case insensitive. However, on extremely large tables this resulted in a significant slow down and furthermore many databases already perform case insensitive queries by default so using the Upper() function was unnecessary.

Now, the Auto-suggest does not use the Upper() function in the generated SQL query, meaning that on those databases that perform case-insensitive queries the auto-suggest is case-insensitive and on those database that perform case sensitive queries, the auto-suggest is case sensitive. The resulting performance improvement on very large tables can be dramatic.

For those situations where you have a database that performs case sensitive queries, but you want the auto-suggest to be case insensitive, a new option in the Auto-suggest builder allows you to explicitly force a case-insensitive query.

 

UX Component - List Control - Detail View - Incremental Refresh - Timestamp Field - Normally, no schema changes are required to the database in order to perform an incremental refresh (i.e. there is no requirement that a timestamp field be added to the table).

An incremental refresh must compute which records on the server were changed since the last time the List was populated. In order to compute which records were changed the checksum (CRC) of the record contents of each record on the server is compared with the checksum of the corresponding record on the device. If the checksum is different, the record was changed and an updated version of the record is sent to the server.

However, a more efficient way of determining if a record was changed is to query for all records modified since the highest timestamp value the last time the List was populated.

Now, if you have a timestamp field in your table, you can direct Alpha Anywhere to use this field for Incremental Updates, rather than the CRC (checksum) method.

To direct the List to use a timestamp field for incremental updates, open the List builder and go to the Detail View pane.

Then check the Use a 'timestamp' field when performing an Incremental Refresh property and then specify the name of the timestamp field.

 

 

UX Component - List Control - Detail View - PhoneGap - Media Files - Ignore Folder - When a List is populated you can specify that all media files (images, videos, audios, etc.) that are referenced in the List should be downloaded to the device so that these media files will be available when the device is offline.

Now you can specify that any referenced media files that are in a folder in the PhoneGap bundle (i.e. in a subfolder inside the www folder of the PhoneGap project) should be ignored when the List computes which files must be downloaded from the server.

The following scenario will make the use case for this option clearer.

 

Assume that your UX contains a List control with this data in two of the rows at the time the PhoneGap project is built:

ID Name Image
1 Alpha myImages/image1.jpg
2 Beta myImages/image2.jpg

 

The myImages folder is part of your Web Project (i.e. it is stored in your Web Project folder) and it contains the files image1.jpg and image2.jpg.

 

When the PhoneGap app is built, the 'myImages' folder is included in the PhoneGap project (the PhoneGap Genie has a property where you can specify Additional Files to be included in the PhoneGap project). You would specify

myImages/*.*

for the additional files.

 

When the PhoneGap app is built, the myImages folder and all of the images in that folder become part of the PhoneGap application (i.e. the myImages folder will be a sub-directory in the www folder on the device) and the images in the List will still display because the Image field is pointing to a local file on the Device.

Now further assume that when you designed the List control you specified that Media files should be downloaded to the device. When you specify this property you specify the folder where the media files should be downloaded. You cannot specify that they should be downloaded to the www/myImages folder on the device as that is a read-only folder.

By default Alpha Anywhere suggests a folder for media file downloads called _AAFiles in a part of the filesystem that you designate.

When you refresh the List, Alpha Anywhere decides if the image must be downloaded by checking for its existence in the target folder (i.e. _AAFiles by default). So when it checks the first record, it will not find an image called myImages/image1.jpg in the target folder, and therefore it will attempt to download this file (even though this file is already in another folder on the device) from the server so it can be stored in the target folder.

Once the download is complete the filename in the Image field will be changed to point to the file in the target folder (i.e. the _AAFile folder).

However, by specifying which folders in the PhoneGap bundle to ignore, you can prevent Alpha Anywhere from downloading any images that are already on the device in the www/myImages folder.

To specify folders in the root www folder to ignore, open the List builder and go to the Detail View pane. Then open the Media files (photos, videos, audio recordings, other) settings dialog.

 

 

In this window, check the Ignore media files in www sub-folder property and then specify the folder name.

 

 

UX Component - List Control - Detail View - .addTableRowsBulk() Method  - Allows you to programmatically add multiple rows of data to a List with a Detail View.

The <listObject>.addTableRowsBulk() method allows you to add an array of new rows to the List.

NOTE: Using the .addTableRowsBulk() method is faster than calling the .addTableRow() method in a loop.

 

Example:

 

var listObj = {dialog.object}.getControl('LIST1');

var dataArray = [

    { FIRSTNAME: 'Cecelia', LASTNAME: 'DeLuca'},

    { FIRSTNAME: 'Cathy', LASTNAME: 'Marsh'}

]

listObj.addTableRowsBulk(dataArray);


 

TransForm - TransForm is a stand-alone service for building mobile, data collection forms (i.e. apps). To use TransForm you do not need an Alpha Anywhere license, but if you also have Alpha Anywhere, there are several features in Alpha Anywhere that make working with TransForm easier. To learn more about TransForm, click here.

To learn more about the TransForm features that are built into Alpha Anywhere, click here.

 

AlphaDAO - Update and Delete Operations - When you execute a SQL UPDATE or DELETE operation, if the WHERE clause does not find any records to operate on the SQL::Connection.execute() method currently returns .F.

However, some developers have requested that the SQL::Connection.execute() method should return .T. and treat the "no records found" condition as a warning and not an error. The SQL::Connection.callResult.rowsAffected property can be checked to see if any work was actually done.

In order to change the default behavior so that the "no records found" condition is a warning you can either manually update the connection string to add this property to the connection string:

A5ReportNotFoundAsWarning=Y

NOTE: This property is not exposed in the connection string builder.

Or alternatively, set a property on the connection object. For example


DIM cn as SQL::Connection
cn.ReportNotFoundAsWarning = .t.

 

 

Web Projects Control Panel - Component Dependencies - You can now right click on a component in the Web Projects Control Panel and select the Show dependencies for this component... menu item to see a list of component that this component calls and a list of components that call this component.

 

 

For example, this dialog shows that the Auto_Customers Grid component is called by the FlyingStartTabbedUI component and that it calls the Auto_Orders component.

UX Component - Builder - Live Preview - The Live Preview pane in the UX builder now lets you select if you want to use Internet Explorer or Chrome for Live Preview. Previously Internet Explorer was used and there was no option to use Chrome instead.

This is now similar to Working Preview which also allows you to select between Internet Explorer and Chrome.

 

UX Component - Arguments - Setting Values on the Client-Side - The value of arguments in a component are typically set on the server-side. Now, a new method - .setArgumentValue() -  allows you to set the argument value on the client-side. After an argument value has been set on the client-side, when the next Ajax callback occurs, the argument will have a new value when the server-side code is executed.

Syntax

{dialog.Object}.setArgumentValue(argName,argValue)

 

Where argName is the name of the argument you want to update. The argName must be uppercase and the argument name in the component definition must also be uppercase.

argValue is the new argument value. It is always a string value. If the argument was defined as being some other type, when the argument value is set on the server-side the value will be converted to the correct type.

UX and Grid Component - serverIsAvailable() Method - Performance - The performance of this method has been substantially improved. If the server is available, the response will be received significantly more quickly. This means that you can use a shorter timeout value in the method.

UX Component - Client-side Templating - Format Directives - New formatting options available for the client-side templates.

In all places where you can edit a client-side template, the Insert format directive hyperlink now shows two new options: 'Friendly' date format and Text format.

 

 

The available text formats are

 

If you select the 'Friendly' date format option a builder is displayed.

You can use click the Edit Date Format button to compose either a relative (e.g. 3 days ago) or calendar (e.g. this month) format.

 

 

The new 'Friendly' date formats are represented in the template as follows:

{date:dateRelative(precision,scope)}

{string:dateStringRelative(formatIn,precision,scope)}

{date:dateCalendar(type,showTime)}

{string:dateStringCalendar(formatIn,type,showTime)}

 

 

Xbasic Genie for SQL Actions - A new genie is available to help developers write Xbasic code that performs CRUD operations against SQL databases.

To access the genie, right click on white space while editing any Xbasic code.

 

 

 

The Xbasic SQL Genie screen is shown where you can select the type of SQL action you want to perform.

 

 

The screen below shows the genie for an UPDATE action.  The bottom half of the window shows the generated code based on the settings made in the top part of the screen.

 

 

Update to Security for HTTP Client Functions - The http_fetch(), http_get(), http_getpost(), and http_post() functions in Alpha Anywhere allow an optional SSL/TLS cipher list to be specified. This allows fine-grained control over TLS connection options when working with remote servers.

Some servers have recently begun rejecting connections from these HTTP functions because of their support for older, less-secure encryption ciphers. To address this, we have updated the default ciphers used when they are not otherwise specified.

These functions now use the cipher list from the httpd_defaultcipherlist() function. This is the cipher list used by the Application Server, and it is also suitable for clients.

 

UX Component - List - Detail View - Customization of Message Box - There are several message boxes that the List with Detail View displays.

The message text, title and icon for these messages can be customized in the Customization section of the Detail View pane in the List builder.

Now you can take complete control over these messages and call your own Javascript functions to display the messages.

 

 

In order to use a custom Javascript function for a message, set the message text to:

javascript:name_of_your_function

 

 

Note: If you write you own Javascript handler for any of these message boxes, you will be responsible for specifyin the Javascript to execute if the user selects the OK button (i.e. confirms, for example, that they want to revert the Detail View).

Web Control Panel - Keyboard Shortcuts - Ctrll+P can now be used to Publish a project and Ctrl+Q can now be used to invoke the Quick Publish command.

Web Applications - Active Directory - Performance of authentication against an Active Directory has been significantly improved.

Alpha Application Server - Self-signed Certificates - The way in which self-signed certificates has been changed. This will allow you to use the Development server with SSL turned on in Google Chrome.

 

Xbasic - handlebars_template_merge() Merge Function - Merges JSON data into a template using Handlebars syntax.

Handlebars is a popular, open source templating library.

This function takes JSON data and a template (that uses Handlebars syntax) and merges the data into the template.

NOTE: This is just a helper function for the low level nodeservices::handlebars.runTemplate() static method.

Example:

 

 

jsondata = <<%str%
{

    firstname:'Fred',

    lastname : 'Smith'

}
%str%

template = <<%str%
Hello {{firstname}} {{lastname}}
%str%

?handlebars_template_merge(template,jsondata)

 

= "Hello Fred Smith"

 

 

Xbasic a5_Create_PDF_From_Template() Function - A helper function for use in a Web Application. The function is used in an Ajax callback. It takes some JSON data, and a template, generates a PDF file from the result of merging the data into the template, and then returns the Javascript code necessary to download the PDF file to the client. The merge syntax can either be Handlebars, or the Alpha Anywhere client-side templating syntax.

Syntax

c JavascriptResult = a5_Create_PDF_From_Template(P e,c template ,c jsondata [,c  syntax = "AlphaAnywhere" [, c javascriptfunctions)


Where

IMPORTANT This function uses the Node PhantomJS module. This module is not installed by default (it is installed on Alpha Cloud so no action is necessary for Alpha Cloud) . You must install it by selecting to the Tools, Packages command then selecting phantomjs from the dialog. This will make PhabtomJS available while you are in development mode. You must also ensure that PhontomJS is available in your published application by going to the Web Project Properties dialog and then clicking on the smart field for Referenced Packages.

 

 

Example

Assume you have a button on a Grid or UX component that makes an Ajax callback. The purpose of the button is to generate a PDF confirmation that the client can download. Assume that the name of the Xbasic function that handles the callback is XBCallback. Here is how this function could be defined:

 

Function XBCallback as c (e as p)

 

dim jsonData as c = <<%txt%

{ Firstname: "John", Lastname: "Harris", amount: 23.45 }

%txt%

 

dim template as c = <<%txt%

<p>Dear {Firstname} {Lastname}</p>

<p>Thank you for your order in the amount of {amount:number('$#,##0.00') }

%txt%

 

dim js as c

js = a5_create_pdf_from_template(e, template, jsondata)

 

XBCallback = js

 

 

end function

 

 

UX Component - ViewBox Control - Partial Templates - A partial template is a template snippet that can be included in another template.  Partial templates are useful if your ViewBox defines multiple Layouts and each of these layouts contain parts that are the same across all of the layouts. The parts that are the same across all layouts would be defined as a partial template and then each layout can include the partial template with this template code

{*partial name_of_partial_template}

 

To define partial templates, select the Partial templates property on the ViewBox Properties tab.

 

 

 

 

Application Server for IIS - License Activation - A change was made in how the IIS Server license activation is performed. This change will improve performance for certain requests under the IIS server.

 

UX Component - HTML Editor - Image and File Upload - Amazon S3 - When you upload an image or a file from the HTML editor, you can now specify a storage connection string as the Upload Folder. If your connection string points to Amazon S3, the file will be uploaded to S3 and a URL pointing to the file on S3 will be injected into the HTML document you are editing.

This new option is especially important when running under the IIS server or on Alpha Cloud, because the option of uploading files to a folder in the webroot is not possible in these environments.

 

PhoneGap App Builder - PhoneGap Version - Added support for PhoneGap 8.0.0 which was recently added to PhoneGap Build. This version updates only the Android platform, although it is a major version update for Cordova Android from 6.3.0 to 7.0.0. The minimum Android API level required for PhoneGap 8.0.0 is 19 (KitKat) and only Gradle builds are supported. These properties will be set automatically within the PhoneGap Builder when you save or save and upload your project to PhoneGap Build when using PhoneGap 8.0.0.

If you have any trouble with plugins, you may need to use an older version of PhoneGap.

 

UX and Grid Component - Date and DateTime Fields - Date Picker - Friendly Value Display - For date and dateTime fields, you can now specify that the value should be displayed using 'friendly' text.

 

Watch Video

 

The 'friendly' text can either display the calendar value in text form (e.g. next Friday at 12:00​am, today, Thursday the 21st of February 2019) or in relative form (in 3 days, in 3 days 2 hours, in 45 seconds).

When you select a relative form the display value will automatically update at an appropriate frequency to make the passage of time. For example, if the initial display for a dateTime value is in 45 seconds, then the display will automatically update to in 44 seconds, in 43 seconds, and so on.

To turn on friendly value display for a date or dateTime field, check the Display value using friendly text? property.

 

 

Once you check this property the Friendly date display settings property will become visible. Click the smart field to open the builder as shown in the image below.

 

 

The builder allows you to make several selections to control how the value will be displayed and at the bottom of the builder you can check to see how various values will be formatted using the settings you have chosen.

 

For the Calendar option, you can specify 3 different formats that control how much detail is used in the display value (Abbreviated, Standard, Extended).

 

For the Relative option you can specify the date parts used in the display (i.e. the Scope) (Years, Months, Weeks, Days, Hours, Minutes, Seconds) and how many of these parts should be used in the display (i.e. the Precision)

 

For example, if you specify the full scope (Years to Seconds) and the full precision (-1) the relative a relative would be be displayed as:

"1 day 8 hours 50 minutes 6 seconds ago"
 

However, if you changed the precision to 2 the same value would be displayed as

"1 day 8 hours ago"

 

Javascript Library - Date Object - Several new methods have been added to the Javascript date object prototype allowing for powerful date formatting and calculations.

 

For full documentation see here.

 

Example:

Consider the following console session for a page that load the Alpha Anywhere Javascript libraries:

var d = new Date();
d.adjust('day',2);
d.toString();
"Sat Feb 03 2018 13:59:42 GMT-0500 (Eastern Standard Time)"
d.toRelative();
"in 1 day"
d.toRelative(2);
"in 1 day 23 hours"

 

Support for 4K Monitors - Improved support for 4K monitors has been added. Previously, some of the lists in various screen in the IDE would appear to be compressed. Now, these lists display normally. However, as a result of these changes, certain screens might not look as "sharp" they did before the 4K support was added.

You can use a new command line argument (-hidpi ) to turn off support for 4K monitors.

For example

alpha5.exe -hidpi

 

 

UX and Grid Component - Lookup Grid - Dynamic Filter - When you define a dynamic filter for a Lookup Grid you can now get the filter value from the result of a Javascript function. Previously you had to get the filter value from a control in the current row of the Grid (if the lookup was for a Grid field), or some control on the UX (if the lookup was for a UX field).

 

 

UX Component - Page Title - You can now set the page title property to a session variable.

 

UX Component - PhoneGap Applications - Changing URL for AJAX Callback at Run-time - When you build a PhoneGap application, the URL for AJAX callbacks is set at the time that you build the application.

You can now change this URL at runtime using the {dialog.object}._updateAjaxURL() method.

 

Syntax:

{dialog.object}._updateAjaxURL(newCallbackURL);
 

Example:

var newCallbackURL = 'https://www.myserver.com/v2';

{dialog.object}._updateAjaxURL(newCallbackURL);
 

   

printQRCode() Function - This function now has a new option to generate the QR code internally, rather than calling the Google API. Generating the QR code internally is substantially faster than using the Google API. The speed difference will be most noticeable in reports that call the prinQRCode() function many times.

Syntax:

 

Syntax

P result =  printQRCode(c value, sizeInPixels = 200, flagURLEncodeValue = .t., flagUseGoogle = .f.)

 

The sizeInPixels and flagURLEncodeValue parameter are ignored if the flagUseGoogle parameter is .f.

 

UX Component - Sample Template - A new sample template UX component is available. This template allows you to create a UX component that allows a site administrator to create new users and set user roles.

When you create a new UX, select this component from the available list of templates:

 

Here is what the component looks like at run-time:

Alpha Anywhere Server - A WARNING message will be written to the Xbasic error log when a query parameter name, etc, has a normalized name that is different from the original name. For example, a variable called 'First-Name' in a Post body gets converted to First_Name because First-Name is not a valid Xbasic variable name.
 

Xbasic - AlphaDAO - MySQL/MariaDB - Geography Queries - Portable SQL now generates the ST_Intersect() function instead of the Intersetct() function for queries that use the portable GeogLocationIsWithinPolygon() or GeogLocationIntersectsLine() functions.

PhoneGap App Builder - PhoneGap Version  - Added support for PhoneGap version cli-7.1.0. PhoneGap Build recently announced support for PhoneGap version cli-7.1.0. This release includes support for iOS 11.2 and includes Cordova iOS 4.5.4, Android 6.3.0 and Windows 5.0.0. This will resolve the plugin dependency issues with the latest plugins that require Android version 6.3.0 or greater. With the release of cli-7.1.0, PhoneGap Build should now support the latest Android plugins.

PhoneGap App Builder - Core Plugin Versions - All of the core PhoneGap plugins now include a version specification that is defined in an external file named phonegap_core_plugins.txt that is included in the PhoneGap folder of the directory that contains the Alpha Anywhere executable file. The versions specified are known to work reliably with PhoneGap cli-7.0.1 and greater. If you would like to load a different version of any core plugin, this file can be edited with any text editor. We suggest you make a backup copy of this file prior to editing.

Application Server - IIS - Crash Dump Files - In the event of a crash of Alpha Anywhere Application Server for IIS, a crash minidump file is written to the log folder. Each minidump file can have a unique name. Due to IIS' ability to recover from a crash, it may not be apparent that a crash has happened which may lead to the crash happening again causing another minidump file to be created. Since minidump files can be quite large, lots of disk space may be consumed. An IIS publish profile now has the ability to limit the amount of spaced used by minidump files and these settings are enabled by default.

 

 

These settings are also available for a published application in IIS Manager under the Logging feature in the Alpha Anywhere Application Server section:

 

 

 

 

Xbasic_execute_Javascript() Function - Execute Javascript code on the server side using the Javascript engine in Node.js

Syntax

p result = Xbasic_execute_Javascript(c jscode)



Where

If you want the Javascript code to return a value, the Javascript code must emit the value by specifying the name of the variable to emit as the last line in the Javascript code. See example below


dim js as c
js = <<%str%
var arr = [];
for(var i = 0; i < 1000; i++) {
    arr.push('String: ' + i );
}
var txt = arr.join('\n');

//we want to return the value of the 'txt' variable, so we emit it by specifying

//the variable name as the list line in the Javascript code
txt;
%str%


pr = xbasic_execute_javascript(js)
 

if pr.error = .f. then

    showvar(pr.result)

else

    showvar(pr.errorText)

end if
 

Alpha Anywhere Development Version - Built-in Version of Chrome - The AlphaAnywhere Development environment has been upgraded to build-in the latest version of Chrome. Previously an older version of Chrome was built-into Alpha Anywhere. As a result of this change certain Chrome features that were not supported in the old version of Chrome will now be available when using Chrome for Working Preview. In addition, Chrome Working Preview will be more responsive and the memory footprint used by the Development Version is reduced.

 

MFC Dependency - Starting with this build, Alpha Anywhere no longer has any dependency on the Microsoft MFC library. While the benefit of this to users may not be apparent, the benefit to Alpha Anywhere is significant and will result in new features that would not previously have been possible.

NOTE: This change should NOT have any effect on the Application Server (both the Classic and IIS servers).

 

UX and Grid Component - Javascript Actions - Duplicate Action - You can now duplicate Javascript actions.

 

 

 

Bugs

UX Component - List Control - Action Javascript - Filter List - When using Action Javascript to filter a List, the builder did not show the correct List of fields on which a search could be defined. The builder showed the fields in the underlying table(s) that the List was based on, rather than the fields in the query that the List was based on.

Grid Component - Alpha Theme - Buttons - Some buttons did not show the hover and pressed state.

Grid and UX components - Dynamic Images - Fixed a regression in dynamic images

Grid Component - Updateable Grid - Display Format and UnFormat Expressions - If an updateable grid had a Display Format expression defined for a column, then when the Grid was updated, the "old" value for that column was not first being "unformatted". As a result, the user would get a write conflict error when trying to update the field.

Grid Component - Export to Excel - Hidden Columns - Column Headings - If you have checked the option to use Grid Column Heading for columns in the Excel file, and you have also checked the option to export hidden columns, the hidden columns will now correctly use the defined Grid Column Headings.

Page Layout Component - Frames - Modern - Modern Frames were not rendering correctly.

IIS Server -- Lockout user until reset by administrator - This option did not work correctly

 

.DBF Tables - Export - SQL Server - Fixed a bug exporting .dbf tables to SQL Server.

UX and Grid Component - Javascript Syntax Checker - No longer reports an error if your Javascript code deletes a variable.

UX Component - Slider - Multi-Valued Sliders - Fixed issue when both min and max buttons were at the max value. User could not drag button to a new value.

Grid and UX Component - SVG Icons - Fixed issue with events and styling on SVG icons.

PhoneGap - InstantUpdate Feature - Fixed an issue where if you installed an app on a device that used the Instant Update feature, and you then created a new baseline app and installed it on the device without first uninstalling the original version of the app, the original version of the app (not the new version), would continue to run.

Grid, TabbedUI and UX Components - SVG Icons - onClick Event - Fixes a bug with the onClick event on an image that uses a SVG icon.

TabbedUI and PageLayout Components - Modern Frame - Show/Hide Button - Fixes a bug that was introduced in the last official update. You will need to edit the component and recalculate the controls.

UX Component - ViewBox refresh - Fixes a bug with the refresh ViewBox data option. This bug was introduced in the previous release.

Alpha Launch - UX Components - Auto-suggest Controls - Fixed an issue where Auto-suggest controls did not work in applications that were running in Alpha Launch.

UX Component - ExpandingMenu Control - Menu Data Genie - Fixed several problems when using the Menu Data Genie to define the choices shown in the ExpandingMenu control.

Tips

UX Component - Drag Scrolling vs. Vertical Scrollbar - Web Applications - In some cases you might have a UX with a Panel Card that contains more content than can be displayed in the Panel Card. Vertical scrolling is required to see the content that is not initially visible. On a mobile device, the user will scroll using drag scrolling.

In a web application, you want the user to see a vertical scroll bar.

However, if you are running the web app on a machine that is touch enabled, then drag scrolling will be enabled, and the vertical scroll bar will not be visible.

Here is how you can force the app to show a vertical scrollbar:

In the client-side onInitializeBegin event: add this code:

if( [condition you want to not drag scroll] ){
    A5.u.drag.useDragScrolling = 'never';
}

 

 

UX Component - List Control - Capture and Restore the List's Scroll Position - In some applications it might be necessary to restore the List's scroll position without actually selecting a row in the List. For example, a List may have been scrolled to a certain position, but no record in the List has been selected. A refresh operation on the List is performed, and now you want to scroll the List back to its previous position.

 

Here is how you can do this (assume that the List ID is 'LIST1'):

 


//capture the scroll position
var eleID = {dialog.object}.getControl('LIST1').contId + '.CONTENTWRAPPER';
var obj = A5.u.element.getScroll(eleID)
{dialog.object}._scroll = obj;


//restore the scroll position
var obj = {dialog.object}._scroll
var eleID = {dialog.object}.getControl('LIST1').contId + '.CONTENTWRAPPER';
A5.u.element.setScroll(eleID,obj.left,obj.top);

 

 

 

 

Xbasic - Working with .Net Arrays


Zero-based versus One-Based Indexing
By default, XBasic arrays are indexed using one-based indexing. This means that the items in the array are referenced using indexes beginning with one (1) for the first entry and continuing on with 2, 3, 4 and so on.

Other environments, including .Net arrays and collections, use zero-based indexing. This means that the first item in the array is referenced with an index value of zero (0) and continues on with 1,2,3 and so on.

When accessing an array or collection in .Net from XBasic, Alpha Anywhere automatically maps one-based indexes in XBasic array references (square brackets – “[]”) to zero-based indexes. This removes the need to remember whether an array reference is for an XBasic array or a .Net array or collection.
 

XBasic Square Bracket References


XBasic Function Calls

 


Example Usage

The interactive wndow session below now shows accessing the System::Data::DataSet Tables collection using the Item property with a numeric or string index:

 

dim ds as system::data::dataset
t1 = ds.Tables.Add("Fred1")
?t1.TableName
= "Fred1"
t2 = ds.Tables.Add("Fred2")
?t2.TableName
= "Fred2"
Tables = ds.Tables.Count
for i = 1 to Tables ; ? ds.Tables.Item[i].TableName + crlf(); next
Fred1
Fred2
?ds.Tables.Item["Fred1"].TableName
= "Fred1"
?ds.Tables.Item["Fred2"].TableName
= "Fred2"

 

 

 

Alpha Anywhere V4.5.2 - Build 4770-5018 14-DEC-2017

NOTE: This build has introduced a bug in the Javascript Action to refresh the data in a UX Component ViewBox control. After you install this update you can install a hotfix for the bug by downloading this file. Click here for instructions on how to install a htofix.

 



 

Videos

UX Component - Tree Control Populating a Tree Control using a SQL Query and Defining a Javascript Event for Each Tree Leaf Node The Tree control can be automatically populated with data derived from a SQL query. When doing this it is common to want to execute some Javascript code when the user selects a leaf node in the tree.

In this video we show how this is done.


Watch Video

Download component

Date added: 2017-11-02
UX Component Selecting Multiple Values in an Auto-suggest or Edit Combo Control The Auto-suggest and Edit Combo controls have always allowed you to set a mode where multiple selections can be made. However, each time you make a selection the pick list is closed and you must reopen the pick list before you can make your next selection.

Now, a new property in these controls allows you to specify that the pick list should stay open after each selection, allowing you to make multiple selections more easily.


Watch Video


Date added: 2017-11-15
UX Component - ControlBars Using the Built-in ControlBar Templates The ControlBar is highly configurable. This allows you to create solutions for many different use cases. There are several common patterns that developers use and for many of these patterns you can get a quick start by selecting one of the pre-defined ControlBar templates. For example, common patterns addressed by the pre-defined templates are:ControlBar with a menu button that animates in a menu from the left or right side of the Panel, ControlBar with buttons that reveal animated drop-down menus, ControlBar with buttons that allow you to create a tabbed user interface.

In this video we show how you can create a new ControlBar from a template and then continue to modify the resulting ControlBar.

Watch Video

Date added: 2017-11-28
UX Component Sample UX Component - Amazon Mobile Shopping Look Alike Example The Amazon mobile shopping App is one of the most recognizable mobile Apps. In this video we show how the look and feel of this App can be recreated using the UX component.

Open the App in a Browser

Watch Video - Overview

How the Products List is Populated
Watch Video
How the Back Button in the ControlBar is Implemented
Watch Video
How the Badge on the Shopping Cart Icon is Implemented
Watch Video
How the Search Box is Implemented
Watch Video
How the Product List Layout is Implemented
Watch Video 1
Watch Video 2
How the Detail View is Implemented using a ViewBox Control
Watch Video 1
Watch Video 2
Watch Video 3

Date added: 2017-12-13
     

 

 

 

Features

Application Server for IIS - Unlicensed Mode - The Alpha Anywhere Application Server for IIS is will now run in unlicensed mode. Five users can be active on an unlicensed server allowing development and testing to be done without needing a license. If more users are needed or the server is running in production a license is required.

This change brings the Application Server for IIS in line with the Standard Application Server for use in development and testing.

You can download the installer for the Application Server for IIS here.

 

Application Server For IIS - Installer - Pending Reboots - When you run the installer for the Application Server for IIS the installer will now warn you if your machine has any pending reboots mandated by previously installed Windows, or other, updates.

UX Component - {dialog.object}.refreshExpandingMenuData() Method - This method makes an Ajax callback to refresh the data in an Expanding Menu. This method is useful if the Expanding Menu control has assigned security or server-side show/hide expressions to any of the branches or nodes in the data for the expanding menu.

For example, after a user has logged into an application, you might want to use this method to refresh the choices shown in the expanding menu so that only choices for the user's role are shown.

Syntax:

{dialog.object}.refreshExpandingMenuData(expandingMenuIds);

 

Where:

 

UX Component - {dialog.object}.{dialog.object}.populateExpandingMenuControl() Method - This method will repopulate the data shown in an Expanding Menu control.

Syntax:

{dialog.object}.populateExpandingMenuControl(id,data)


Where:

 

Example:

				

var obj = {dialog.object}.getControl('EXPANDINGMENU1');
var data = {
	items:[
		{
			html: 'Category 1', 
			value: 'category1',
			icon: 'svgIcon=#alpha-icon-addCircleBorder:icon,24',
			action: '',
			children: [
				{
					html: 'Action 1', 
					value: 'action1',
					action: 'action:1',
					icon: 'svgIcon=#alpha-icon-bandAidCrossed:icon,24'
				},
				{
					html: 'Action 2', 
					value: 'action2',
					action: 'action:2',
					icon: 'svgIcon=#alpha-icon-bellRing:icon,24'
				}
			]
		},
		{
			html: 'Category 2',
			value: 'category2',
			action: '',
			icon: 'svgIcon=#alpha-icon-heartSolid:icon,24',
			children: [
				{
					html: 'Action 4', 
					value: 'action4',
					action: '',
					icon: 'svgIcon=#alpha-icon-map:icon,24',
					children: [
						{
							html: 'Action 4a', 
							value: 'action4a',
							action: 'action:4a',
							icon: 'svgIcon=#alpha-icon-trendingDown:icon,24'
						},
						{
							html: 'Action 4b', 
							value: 'action4b',
							action: 'action:4b',
							icon: 'svgIcon=#alpha-icon-trendingDown:icon,24'
						}
					]
				},
				{
					html: 'Action 5', 
					value: 'action5',
					action: 'action:5',
					icon: 'svgIcon=#alpha-icon-trendingDown:icon,24'
				}
			]
		},
		{
			html: 'Category 3', 
			value: 'category3',
			action: '',
			icon: 'svgIcon=#alpha-icon-shield:icon,24',
			children: [
				{
					html: 'Action 7', 
					value: 'action7',
					action: 'action:7',
					icon: 'svgIcon=#alpha-icon-shuffle:icon,24'
				}
			]
		}	],
	actions: {
		action: function(arg){
			alert('Action' + arg);
		}
	}
}
{dialog.object}.populateExpandingMenuControl('EXPANDINGMENU1',data);
					
		

sql_upsert() Function - The sql_upsert() function is a high level Xbasic function that complements the sql_update() and sql_insert() functions. The sql_upsert() function will update a record if the record exists in the database. Otherwise it will insert a new record into the database.

Syntax

    p result = sql_upsert(A connection,c tablename,c fieldValuePairs [,c primaryKey [, a primaryKeyValue [, L execute [, P e ]]]])

 

Where

 

Example:

 


dim cn as sql::Connection

cn.open("::Name::myconnstring")
tablename = "mytable"
fieldsValuePairs = <<%str%
name=fred smith

date of birth=1952/12/18

salary=78000
%str%
 

'You can also specify field values using JSON
fieldsValuePairs = <<%str%

    "name" : "fred smith",
    "date of birth" : "1954/11/25",

    "salary" : "78000"
}
%str%

primaryKey = "id"
primarykeyValue = "1"

p = sql_upsert(cn,tablename,fieldsValuePairs,primaryKey,primaryKeyvalue)

 

Amazon Look Alike Sample Mobile Application - A new sample template is available. The Amazon look-alike sample mobile application is a sample Alpha Anywhere application designed to show how a familiar mobile app could be built using a UX component.

You can load the sample app in your web browser, or on your mobile device from this url:

http://alphamediacapture.s3.amazonaws.com/sampleamazonlookalikeapp/index.html

 

You can watch a video showing a quick overview of the application by clicking here.

 

NOTE: When you create a new UX Component, you can select this sample application from the list of template applications.

 

The images below show screenshots from various parts of the application:

 

 

 

Main App screen. This screen shows a List control listing the various products that can be purchased. Each row in the List is rendered using a freeform layout template that uses Alpha Anywhere's client-side templating feature to create a highly customized layout.

 

 

Navigation menu. The navigation menu is shown when the user taps on the menu icon in page header. The menu it rendered using the Expanding Menu control.

 

 

This is the Detail View for a particular product. This Panel is shown when the user taps on a row in the List. The ViewBox control is used to render the Detail View and the template that is used in the ViewBox control to render the Detail View makes extensive use of client-side templating features.

 

 

This is the scrolled view of the Detail View for a particular product.

 

 

This is the shopping cart showing a list of products that have been added to the cart. This Panel also uses a List control with a freeform Layout to display each row in the shopping cart.

Notice that the shopping cart icon in the header has a badge indicating how many products are in the cart.

 

 

This screen shows the page that is displayed when the user taps on the Quantity button on the product detail page.

 

After the user selects a quantity, the Quantity button on the product detail page is updated to show the selected quantity.

 

Understanding How the App Was Built

The entire App was built using a single UX component as shown in the image below.

 

 

The key building blocks of the app are:

 

The app structure is shown below:

 

 

Each 'page' in the App is contained in a Panel Card and the Panel Cards are contained in a Panel Navigator. The Panel Navigator has been configured as "Programmatic" - meaning that the user cannot swipe left-to-right, or right-to-left on a Panel to navigate to the next Panel. Instead Javascript code is used to control which Panel is shown in the Panel Navigator.

The Panels in the App are:

 

NOTE: This demo app is not a complete application.  It is only meant as a teaching tool to show how a compelling mobile user interface can be created using the UX components. For example, the navigation menu displays, but when you make a selection from the menu, the product list is not updated.

 

Videos Explaining How Various Features Are Implemented

 

How the Products List is Populated

    Watch Video

How the Back Button in the ControlBar is Implemented

    Watch Video

How the Badge on the Shopping Cart Icon is Implemented

    Watch Video

How the Search Box is Implemented

    Watch Video

How the Product List Layout is Implemented

   Watch Video 1

   Watch Video 2

How the Detail View is Implemented using a ViewBox Control

   Watch Video 1

   Watch Video 2

   Watch Video 3

 

JSON_shred() Function - This function has been enhanced. The input schema that describes how the JSON should be shredded is now optional. Also, the function can automatically inject linking values into the JSON if the JSON does not already have appropriate linking values. If the input schema is not specified then linking values are automatically injected.

The purpose of the JSON_shred() function is to take a complex JSON document (with one or more nested arrays) and decompose the JSON into multiple flat arrays, none of which have nested arrays.

The new syntax for the function is:

 C result =  JSON_shred(C json [,C schema [,C topArrayName [,L flagAddSurrogatePrimaryKey [,C surrogateKeyName ]]]])

 

Where:

 

Example:

dim json as c 
json  = <<%str%
[
    {"Firstname": "John", "Lastname" : "Smith", "City" : "Boston", "State" : "MA", "Children": [
        {"Name" : "Callie", "Age" : 5},
        {"Name" : "Griffin", "Age" :3},
        {"Name" : "Luke", "Age" : 1}
        ]
    }, 
    {"Firstname": "Henry", "Lastname" : "Rhodes", "City" : "New York", "State" : "NY", "Children": [
        {"Name" : "Howard", "Age" : 15},
        {"Name" : "Robert", "Age" : 11}
        ]
    }
]
?json_shred(json)

{
    "__top": [
        {
            "__surrogatePrimaryKey": "475750b196554658b2518fde4bfaec6e",
            "Firstname": "John",
            "Lastname": "Smith",
            "City": "Boston",
            "State": "MA"
        },
        {
            "__surrogatePrimaryKey": "c970381d48aa4abfa92d0f46d02ead27",
            "Firstname": "Henry",
            "Lastname": "Rhodes",
            "City": "New York",
            "State": "NY"
        }
    ],
    "Children": [
        {
            "ParentLinkingValue": "475750b196554658b2518fde4bfaec6e",
            "LinkFieldName": "__surrogatePrimaryKey",
            "__surrogatePrimaryKey": "16963be3261c4d82a50152dfb18f9ff0",
            "Name": "Callie",
            "Age": 5
        },
        {
            "ParentLinkingValue": "475750b196554658b2518fde4bfaec6e",
            "LinkFieldName": "__surrogatePrimaryKey",
            "__surrogatePrimaryKey": "556ed6b0264544bd93ebe1382578347a",
            "Name": "Griffin",
            "Age": 3
        },
        {
            "ParentLinkingValue": "475750b196554658b2518fde4bfaec6e",
            "LinkFieldName": "__surrogatePrimaryKey",
            "__surrogatePrimaryKey": "32558171e17c41f88dffc6594b4f73c3",
            "Name": "Luke",
            "Age": 1
        },
        {
            "ParentLinkingValue": "c970381d48aa4abfa92d0f46d02ead27",
            "LinkFieldName": "__surrogatePrimaryKey",
            "__surrogatePrimaryKey": "7ea305b5205844c5abde8728b68f08ae",
            "Name": "Howard",
            "Age": 15
        },
        {
            "ParentLinkingValue": "c970381d48aa4abfa92d0f46d02ead27",
            "LinkFieldName": "__surrogatePrimaryKey",
            "__surrogatePrimaryKey": "98ff8b3ccc1b4fa1a79bdee2620daee2",
            "Name": "Robert",
            "Age": 11
        }
    ]
}

%str%

 

Dynamic Storage Connection Strings - Storage - SQL Server Reporting Services (SSRS) - Alpha Anywhere has had the concept of dynamic connection strings for AlphaDAO connection strings for some time now. But dynamic connection strings for storage and SSRS did not exist. A dynamic connection string is particularly useful in multi-tenant SaaS applications. Now, you can define dynamic storage connection strings for both storage and SSRS.

A dynamic connection string will resolve differently based on a the value of a session variable.

To define a dynamic storage connection string, your named connection string must start with DynamicConnection_. For example: DynamicConnection_myS3Storage.

You must also have a session variable named

__protected__<name>

where <name> is the text to the right of DynamicConnection_ in the named connection string.

 

So for example, if your named connection string is:

DynamicConnection_myS3Storage

You would need a session variable called:

__protected__myS3Storage

 

When the named connection string is resolved, it will resolve to the value of the __protected__myS3Storage session variable.

 

Xbasic csv_to_json() Function - Escaping Doublequotes - This function now supports two different methods for escaping double quotes.

 

The default is use use two double quote characters. .e.g

"fred","smith","the ""computer"" store","boston"

 

But you can also use Javascript style escapement. e.g.

"fred","smith","the \"computer\" store","boston"

 

Syntax:

c json = csv_to_json(c csvtxt, c escapeMethodForQuotes)

 

Where:

 

 

UX Component - Frame Container - Modern Frames - If a modern frame container is configured to have a show/hide button, you can specify that if the current frame is opened and another frame is subsequently opened, the current frame will be closed.

 

 

UX Component - Mobile Applications - Panel Card - Drag Scrolling - Previously if you dragged on an input control in a Panel Card, the Panel did not scroll. Now, as long as you have not actually given focus to the input control (i.e. the keyboard has not come up) then the panel will still scroll.

 

 

UX Component - ControlBar Builder - User-Defined Templates - You can now save a ControlBar that you have designed as a template. Your user-defined templates will be listed when you click the Load Sample ControlBar hyperlink on the Home pane of the ControlBar builder.

 

 

To save the toolbar that you are currently editing in the ControlBar builder as a template, click the Save ControlBar as a Template hyperlink on Home pane of the ControlBar builder.

 

The dialog shown below will be displayed where you can give the template a name and a description. The description can use HTML markup.

 

 

After you have saved the template, you can save an image of how the ControlBar looks. The image filename that you must use is shown in the next dialog.

When you use the Load Sample ControlBar command the image you have saved will be shown in the list of available templates, making it easier to choose the template you wish to use.

 

 

 

Application Server - Publishing - The publish genie now has an option on the 'Clear Publishing History' button to clear the publish history for just the currently selected publish profile. The ability to clear all history is still available as an option.
 

UX Component - New Starter Template for Mobile App - A new starter UX template is available. The template, called MobileAppFramework_FlyInMenu_to_select_Active_Panel ) is a Panel Navigator, with multiple Panel Cards, and a Control Bar with a menu button that displays an expanding menu that flies in from the left.

 

 

 

Xbasic - Arrays - Change_type() Method - Changes the data type of an Xbasic array.

When you create an Xbasic array by parsing some JSON text, the array's type is set to 'A'. This is because a JSON array can contain items that are of different type.

For example, consider the following code

 

dim json as c

json = <<%txt%

[

    {name: "fred"},

    3

]

%txt%

 

dim p as p

p = json_parse(json)

 

If you were to check the type of p[1], (using typeof(p[1]) ), it would return 'P'.

However, if you were to check the type of p[2], it would return 'N'.

So the array elements in the array can be of any type. You can also dim an array where the items can be of any type like as follows:

dim array1[10] as A

 

Now consider a JSON string that defines an array in which all items are of the same type:

 

dim json as c

json = <<%txt%

[

    {name: "fred"},

    {name: "john}

]

%txt%

 

dim p as p

p = json_parse(json)

 

In this case all of the elements in the array are of type 'P'.

However, if you insert or append elements to the array, the new elements will be of type 'N' and not 'P' as you might have expected. This is because the internal type of the array is 'A' (as is always the case when an array is created by parsing a JSON string).

In some cases you will want to change the type of the array to a specific type so that items inserted into the array, or appended to the array are also of the same type as the other items in the array.

For example:

 

dim json as c

json = <<%txt%

[

    {name: "fred"},

    {name: "john}

]

%txt%

 

dim p as p

p = json_parse(json)

dim result as c

result = p.change_type("P")

if result <> "" then

    ui_msg_box("Error","Could not change array type: " + result)

end if

p.insert(1,1)

?typeof(p[1])

= "P"   '<<----- would have been 'N' had the .change_type() method not been called!

 

UX Component - ControlBar - ControlBar Builder - Pre-defined Templates - New pre-defined templates are available when you create a new ControlBar from a template and the template picker has been enhanced to show a preview of each template.

Watch Video

 

When you create a  new ControlBar, you can set all of the properties in the ControlBar by selecting a template (i.e. sample ControlBar). To select a template, click the Load Sample ControlBar hyperlink on the ControlBar builder Home pane.

 

 

When you click the hyperlink a window showing the templates is shown:

 

 

 

 

UX Component - ControlBar - DisclosureButtons - Disclosure Position - Three new disclosure positions are now available: flyout, flyout-element and flyout-element-cover. Using these positioning directives, it is possible to create controlbars with dropdown menus. See example below.

 

 

 

 

In the image below, the button on the toolbar opens another disclosure positioned using the flyout-element position.

 

 

 

NOTE Sample ControlBars that use the new flyout-element position directive can be seen by selecting the Load Sample ControlBar hyperlink on the ControlBar builder Home tab.

 

sql_import() function - Upsert - The SQL_Import() function is a helper function that imports new records into a SQL table. It is called a 'helper' function because it is an alternative to writing the low level Xbasic AlphaDAO commands to import data. This function now supports both 'insert' and 'upsert'. An 'upsert' performs an update on existing records and an insert if there is no existing record.

The syntax for the function is now:

p result = sql_import(connectionString as c, tableName as c , tableOwner as c, csv_or_json_data as c , replicateIdentity = .f., inputfield_to_sql_table_column_map = "", action="insert", primaryKey = "")

 

Where:

 

 

Example

p = sql_import("::name::myconnstring","table1","","c:\data\datatoimport.xlsx",.f.,"","upsert","id")


 

UX Component - List Control - Freeform Layout - List Item Footer - Freeform layouts now support the List-item Footer property. The state of the list item footer can be toggled on each row from open to closed, or vice versa using the <listObject>.toggleRowExpander() method.

 

UX Component - Multi-select Token Control - Keep List Open - A new option has been added to the Multi-select Token Control to keep the pick list of choices open after the user makes a selection.

 

UX and Grid Components - Arguments - Upper Case Names - When you add a new argument or rename an existing argument, the argument name is now converted to uppercase. By using the convention that argument names are always uppercase, a class of bugs that can result when the same argument name is used in multiple linked components is used and in each of these components, the argument name is defined using a different case.

UX Component - List Control - Detail View - onStateChanged Event - A new event has been added to the List control. The onStateShanged event fires when the Detail View goes from clean to dirty, or vice versa.

UX Component - Auto-Suggest and Edit-Combo Control - Multiple Selections - Keep List Open - The Auto-suggest and Edit Combo controls have always allowed you to set a mode where multiple selections can be made. However, each time you make a selection the pick list is closed and you must reopen the pick list before you can make your next selection.
 
 Now, a new property in these controls allows you to specify that the pick list should stay open after each selection, allowing you to make multiple selections more easily.

 

 

If you have turned on multiple selections, you can delete previously made selections by either backspacing to delete one character at a time, or use Shift+Cntrl+Backspace to delete complete selections.

If you have turned on multiple selections, you can prevent the user from selecting the same value more than once by setting the Allow duplicate selections property.

 

PhoneGap App Builder - Core Plugins And Some Key 3rd Party Plugins - Added a version specification to all core and some essential 3rd Party Plugins plugins to resolve problems with updated plugins and Android on PhoneGap Build.

Many of the core plugins were updated recently and specified a requirement for a minimum PhoneGap version of Android 6.3.0. PhoneGap Build cli-7.0.1 (the latest release supported by PhoneGap Build) includes Android PhoneGap Version 6.2.3 so the changes to the plugins configuration files causes the build to fail on the current release on PhoneGap Build. This change ensures that PhoneGap Build will work with the specified plugins.

PhoneGap App Builder - 3rd Party Plugins - Added support for the PDF417-Phonegap plugin. This plugin is a small but powerful scanner that handles bar code and PDF417 scanning.

 

Alpha Style Sheet - SVG Icons - Several new SVG icons have been added to the Alpha stylesheet. These are:

 

 

 

UX Component - List Control - List Virtualization - onNavigate Event - The onNavigate event's behavior is different depending on whether the list is virtualized or not. If the List is not virtualized, the onNavigate event fires when the List is scrolled. If it is, then the onNavigate event fires when the user navigates to a new page of records.

In order to allow the behavior of this event to be consistent regardless of the virtualization option, a new property has been added to the list. The onNavigate event behavior property can be set to Navigate, Scroll or Both. When set to Scroll, the behavior is the same as a non-virtualized list.

 

 

Application Server - OpenSSL - Updated to build 1.0.2m of OpenSSL.

Web Security - Utility for SQL tables in Standard Server - A revised utility has been added to the 'Utilities' option in the Web Security menu when using SQL based tables on the standard server. The new utility will still verify if the defined security tables can be found, but has additional options.

If the security system connects to the SQL tables with Active Link tables, the utility has an option to 'Validate Field Maps'. The action will verify if the field map saved in the Active Link tables map to the correct field names in the SQL table.

The option will only check a single table if one is selected. If a table is selected, the option 'Clear Selected' will remove the selection and allow checking all tables.

The option 'Show Connection String' will show the actual connection string used by a table if the table is selected. The normal configuration would have the same connection for all tables.

Errors cannot be corrected if using Active Link tables, but the utility will show a message on close if any errors were found

Changes can be made and saved if the security system is using a 'DataLink' file in place of Active Link tables. The option to 'Show Connection String' is still shown, but the option to 'Validate Field Maps' will open a genie to remap the fields if any errors were found in the existing map. The genie will only allow selecting fields that are of the correct data type and length.

A new option is shown to 'Change Connection String'. This shows a list of available connections and can change the connection for all tables. The utility will check if the current tables exist in the new connection and will run the validation option is tables with the same names are found.


Another new option is 'Select New Table'. This will show a list of tabled found in the SQL database that uses the connection. When a table is selected, the field map validation will run to allow remapping the field as needed. This option can also create a new table in the target database, but will not populate the new table with any data.

Changes can be saved by the 'Save Changes' button which is activated if any changes were made.

 

PhoneGap App Builder - iOS Launch Images - Added static (legacy) image generation support for iPhone X and the 10.5 inch iPad Pro launch images. If you are planning to support the new iPhone X and/or the 10.5 inch iPad Pro, you previously had to use storyboard images for your app launch image. This is no longer the case. If you choose to use static (legacy) launch images, then the appropriate size is automaticaly generated for the iPhone X and the 10.5 inch iPad Pro. Remember to center weight your image (look at Twitter's launch image) and verify that each generated image looks correct. The iOS launch images can be found in the PhoneGapProjects\ProjectName\www\res\screen\ios folder.

PhoneGap App Builder - PhoneGap Project Template The PhoneGap new project template was modified to support better code formatting for legacy (static), iOS Storyboard and Android 9-Patch launch images. These sections are dynamically replaced within the PhoneGap config.xml file when the launch and storyboard images are generated by the PhoneGap App Builder genie.

UX Component - List Control - No Records in List HTML - Specify Message Using Javascript - The List Builder allows you to specify a message to show in the List if there are no records in the List.

Previously, you could only define some static HTML to display. Now you can specify some Javascript code to return the message to be shown. To specify that the message is returned by some Javascript code, prefix the message with javascript:

For example, assume that you had defined a local function called norecordsmessage in the List Builder  (Turn on the optional Javascript tab in the List Builder and define a function at the This object level).

You would set the No Records HTML to:

javascript:this.norecordsmessage()

 

You can also include a5-item attributes in the message text. For example, assume you wanted to display a message if the user tapped on the no records message. Assume also that the message was to be returned by a local function called norecordsmessage(). Here is how this could be done:

First, define an item in the List Builder's Items tab (by turning on the optional Template Items tab - check the box at the bottom of the List Builder window. For example, you could define an item called 'norecords' that displayed a message when clicked.

Then define the norecordsmessage function as follows:

 

return '<span a5-item="norecords">List has no records</span>'

 

 

Xbasic Functions - convert_ts_to_js() - Converts TypeScript files (with .ts extension) to Javascript files (with same name, but .js extension)

 

Syntax

result = convert_ts_to_js(files)

 

Where

 

UX Component - Client-side Event - OnBeforeCreate - Fires before any code to render the UX is executed. Allows you to change settings in the Alpha Anywhere Javascript library that affect how the UX is rendered. For example you could override the definition of the A5.listBox.prototype.populate() method in this code.

NOTE: The {dialog.object} object cannot be referenced in the code for this event handler as it has not yet been instantiated.

Xbasic - a5_XbasicTreeToJSONTree() Function - This function, which takes a CRLF delimited string, and converts it into a complex JSON structure that can be used to populate a Tree or Menu control, has been enhanced and now allows you to define the Javascript code to execute when the user clicks on a tree leaf.

 

Consider the following example, which produces a tree showing Countries, Cities, then ContactName. ContactName is the tree leaf. When the user clicks on a leaf, you want to call a Javascript function. The data for the tree should come from a SQL query.

Here is how this is achieved:

 

dim cn as sql::Connection
cn.open("::Name::northwind")
cn.PortableSQLEnabled = .t.
dim sql as c
dim flag as l

'define the sql query that will return the data in the correct format
sql = <<%str%
select country, city, concatenate(contactname,'```onclick:findCustomer(','''',customerId,''')') from customers where not (country = '') order by country, city, contactname
%str%

flag = cn.Execute(sql)
dim txt as c
txt = cn.ResultSet.tostring(-1,-1,.t.,"|")
'this will generate a crlf delimited string like this
'France|Nantes|Carine Schmitt```onclick:findCustomer('FRANR')
'France|Nantes|Janine Labrune```onclick:findCustomer('DUMON')
'France|Paris|Dominique Perrier```onclick:findCustomer('SPECD')
'France|Paris|Marie Bertrand```onclick:findCustomer('PARIS')
'France|Reims|Paul Henriot```onclick:findCustomer('VINET')'

'notice that the tree branches are separated by a | character.
'the leaf nodes specify an onclick event.
'the syntax for the onclick event is ```onclick:javascript to execute

'notice that we pass the primary key to the leaf as the argument to the function

txt = a5_XbasicTreeToJSONTree(txt,"|","html")

 

 

The resulting JSON string is:

 

[
  {
    "html": "Argentina",
    "children": [
	          {
		    "html": "Buenos Aires",
		    "children": [
			          {
				    "html": "Patricio Simpson",
				    "onClick": function() { findCustomer('CACTU')}
				   },
				   {
				     "html": "Sergio Gutiérrez",
				     "onClick": function() { findCustomer('RANCH')}
				   },
				   {
				     "html": "Yvonne Moncada",
				     "onClick": function() { findCustomer('OCEAN')}
				   }				
		]
           }
   }......
]
			

UX Component - Spreadsheet Input Control - Get and Set Column State - Two new methods have been added to the control

 

Example

 

var obj = {dialog.object}.getControl('myspreadsheetcontrol_1');

var json = obj.getColumnState()

//store the column state in local storage

localStorage.setItem('columnstate',json);

 

 

 

//restore the column state

var obj = {dialog.object}.getControl('myspreadsheetcontrol_1');

var json = localStorage.getItem('columnstate');

obj.setColumnState(json);

UX Component - List Control - Media Files - Events - In a disconnected application you can configure the media files in the List to download to the mobile device and be stored in the filesystem on the device. The UX component will fire the beforeMediaFiles download and afterMediaFilesDownload events. Previously, even if there were no media files to download, these events would fire. Now, if there are no media files to download a new event, onNoMediaFilestoFetch will be fired.

 

UX and Grid Components - Reports - Send via Email - A new option in the Action Javascript command to display a report, now allows you to email the report rather than displaying it.

 

 

When you check the Email report property the Email settings property is shown when you can configure the email that will be sent with the report as an attachment.

The Email Settings dialog is shown below.

 

 

UX Component - Frame Control - Modern Frame - Set Open/Close State Programmatically - A new method allows you to set a modern frame to be open. closed, or to toggle its state.

The method, {dialog.object}.frameOpenStateChange(frameId, state) takes two arguments:

Bugs

Alpha Style - IE 11 - Browser Hang - Under some circumstances it was possible to hang IE 11 when using a Grid or UX component that used the Alpha style. The Alpha style uses SVG icons for all icons shown in the components. If a button had an SVG icon and you clicked directly on the icon, and as a result of the click, the icon was replaced (perhaps with a disabled version of the icon), IE11 would occasionally hang.

 

UX Component - SpreadsheetInput Control - Column Width - The column width property was not being honored when the control was rendered.

Alpha Anywhere Server for IIS - Install Error - An install error introduced in approximately build 4710 has been corrected.

bus_days_between() Function - Fixed a bug in this function when using a .dbf table for the list of holidays. The bug did not exist when using a SQL table for the holiday list.

AlphaCloud - All Components - Local CSS - SASS - If any local CSS defined in a component used SASS syntax, the definition was not properly converted to CSS. This bug was a recent regression.

SASS Processing - This build now includes a new version of the SASS processor that converts SASS to CSS. This new SASS processor can report errors in the input SASS file.

UX and Grid Components - Client-side Watch Expressions - Stack depth exceeded Error - Certain types of client-side watch expression (for example myFunction('{grid.componentName}'), would cause a 'stack depth exceeded' error message when the component was saved.

Page Layout Component - Fixed an issue when a Page Layout component contained a Grid component.

Tips

UX Component - Edit-Combo Control - Automatically Displaying the List of Choices - In some situations you might want the pick list for an edit-combo box to be displayed automatically as soon as the user gives focus to the control.

This is easily done by getting a pointer to the button that opens the pick list and then calling the object's .click() method.

For example, assume that the variable name for your edit-combo control was MYEDITCOMBO. You could add this code to the control's onFocus event:

 

ele = $('DLG1.V.R1.MYEDITCOMBO.BUTTON');
ele.click()

 

However, on a mobile device this will not work because the events are all abstracted on a mobile device. To get the above code to work on a both a standard desktop browser and a mobile device change the code to use the $e.execute() method, which allows you to execute abstract events.

 

ele = $('DLG1.V.R1.MYEDITCOMBO.BUTTON');
$e.execute(ele,A5.d.evnts.click);

 

 

 

 

Alpha Anywhere V4.5.1 - Build 4642_4981 12-Oct-2017

Videos

UX Component - List Control Reorder List Rows by Dragging Row to a new Group when Client-side Grouping is Enabled When client-side grouping is enabled in a List, the order of the rows in the List is determined by the sort expression that is applied to the data so that the List data can be grouped correctly. That means that if you drag a row to a new position, and then drop, the row will immediately snap back to its original position (because the client-side sort will be re-applied to the List data).

However, you might want to use drag reorder to move a row from one group to another. This is done by changing data in the row that is moved so that in the onMoveEnd event, the data in the row is updated and then, when the client-side sort is applied to the List data, the row will continue to appear in the target group.

In this video we show how a list of customers, grouped by Country, can be re-arranged by dragging a customer from one country to another.

Watch Video

Download component

Date added: 2017-09-14
UX Component - Spreadsheet Input Control Using the Spreadsheet Input Control In certain applications where a user needs to input data quickly, a spreadsheet style data entry control can be very efficient.

In this video we show how you can add a Spreadsheet Input control to a UX component.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Download component

Date added: 2017-10-02
     

Features

{dialog.Object}.frameOpenStateChange(frameId,state)"
a2[..].description = <<%html%
Sets the open/closed state of a Frame control. Frame control must be configured as a 'Modern' frame and must have
the 'Has show/hide buttons' property checked. Where: <br>
 

 

 

 

 

PhoneGap App Builder - Added PhoneGap CLI Support for Cordova Version 7.0.1  - Added support within the PhoneGap CLI builder for Cordova Version 7.0.1, Android Studio 2.3.3 and XCode Version 9.0.

Handling of Launch Images, Splashscreens and Icons was modified and tested with the latest releases of PhoneGap, Android Studio and Xcode.

Note: The script for Android Studio 2.3.3 was modified to kill all aapt.exe (Android Asset Packaging Tool) instances that remain open after a successful Android Cordova Build. This appears to be a bug in the Windows Android SDK or Cordova 7.0.1.

 

Xbasic - JSON - extension::json::ForEachString() Method - This method is similar to the Xbasic *for_each() function, except that it is designed to operate on property values in a JSON string.

 

For example:


dim json as c = <<%str%
{
    "name" : "name Smith " ,
    "alias" : [ "jj " , "name " ] ,
    "id"     : {
        "name" : "name_01 "
    }
}
%str%
 

Notice that the string 'name' appears in the above JSON as both a property name and also in a property value.

We want to change 'name' to 'John', without changing the names of any of the property values. Also, note that each property value has trailing spaces.
 

'change 'name' to 'John'

json = extension::json::ForEachString(json,"strtran(value,'name','John')")
 

'trim trailing spaces from each property value
json = extension::json::ForEachString(json,"trim(value)")
 

Result:


{
    "name" : "John Smith" ,
    "alias" : [ "jj" , "John" ] ,
    "id" : {
        "name" : "John_01"
    }
}
 

Notice that none of the property names were changed.

 

UX Component - SpreadsheetInput Control - A new control type is now available in the UX component. The SpreadsheetInput Control allows you to display a spreadsheet style grid of cells in which the user can enter/edit data. The spreadsheet columns can be resized and also reordered.

For example, in the image below, a SpreadsheetInput Control has been defined with 3 columns and 5 rows. The user can use keyboard navigation (tab, shift-tab, up and down ) to move between the cells in the control.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Download component

When the UX is submitted, the data in the control is submitted as a JSON string.

 

For example, if the control had been filled in as shown below:

 

then, when the UX was submitted, the data submitted for the SpreadsheetInput control would be as string with this value:

 

"[{"field1":"alpha","field2":"beta","field3":""},{"field1":"","field2":"","field3":"gamma"}]"

 

 

To, add a SpreadsheetInput control to a UX, select the [More..] control from the Data Controls section of the UX toolbox.

 

 

 

Then select the SpreadsheetInput control from the list.

 

 

To configure the control, click the smart field for the Control properties.

 

 

 

This will open the genie where you can configure the control.

 

 

The most important property to configure is the Column definitions property. This property allows you to define the columns shown in the SpreadsheetInput control.

Click the smart field to open the editor, as shown in the image below.

 

 

You can add columns one at a time by clicking the Add Column button. You can click the Quick Select using Genie hyperlink to add columns to match the fields in a SQL table.

 

The onNavigate property allows you to specify Javascript code to execute when a cell in the control gets focus.

 

Defining Row Prefixes and Suffixes

You can define row prefixes (i.e. row labels) and row suffixes so that the control looks even more like a spreadsheet. The prefix displays at the left side of each row and the suffix displays at the right edge of each row. For example, in the image below a prefix has been defined to show the row number.

 

Here is how the control is configured to show the prefix:

The Has row prefix (label) property is checked.

The Row prefix HTML is a defined using Javascript code that can reference row - the zero based row number and data - the array of data with which the control is populated. To show the row number as the row prefix, the Javascript for the Row prefix HTML is set to:

return (row + 1);

 

The Width property is set to 50px to set the width of the prefix column.

The Style property is set to font-size: 75%; text-align: right; to make the font slightly smaller than the text in the input control and also to right align the text in the row labels.

 

 

 

Methods

 

Since the SpreadsheetInput control is a standard UX Data Control, you can use the {dialog.object}.setValue() method to populate the cells in the control with data and the {dialog.object}.getValue() method to get the data in the control. When you use these methods, the value is a JSON string.

For example, if the SpreadsheetInput  control has 3 columns (field1, field2 and field3), you could use the following Javascript to populate the control:

var _data = [

    {field1: 'alpha', field2: 'beta'},

    {field2: 'gamma', field3: 'delta'},

    {field3: 'epsilon'}

];

var _string = JSON.stringify(_data);

{dialog.object}.setValue('mySpreadsheetControl',_string);

 

.setColumnAndPopulate() Method

You can also dynamically change the columns shown in the control to match the columns in some data with which you want to populate the control. For example, say that the SpreadsheetInput control was initially configured to show a single column (say 'Field1') and you wanted to populate it with the the following data:

 

[

    {firstname: 'John', lastname: 'Smith', city: 'London'},

    {firstname: 'Harry', lastname: 'Jones', city: 'Boston'},

    {firstname: 'Winston', lastname: 'Flowers', city: 'Harare'}

]

 

You can call the control's .setColumnsAndPopulate() method.

For example:

var obj = {dialog.object}.getControl('mySpreadsheetControl');

var _data = [

    {firstname: 'John', lastname: 'Smith', city: 'London'},

    {firstname: 'Harry', lastname: 'Jones', city: 'Boston'},

    {firstname: 'Winston', lastname: 'Flowers', city: 'Harare'}

]

obj.setColumnsAndPopulate(_data);

 

 

The columns shown in the control will now be 'firstname', 'lastname' and 'city'.

 

.getColumnState() and .setColumnState() Methods

Since the columns in the Spreadsheet input control are resizeable and reorderable, you might want to capture the state of the Spreadsheet input control's column layout so that you can restore it the next time the user runs the component.

 

For example

var obj = {dialog.object}.getControl('myspreadsheetcontrol_1');

'get the spreadhseet control state as a JSON string

var json = obj.getColumnState();

 

'store in local storage

localStorage.setItem('spreasheet_01_State',json);

 

Then, to restore the state

var json = localStorage.getItem('spreasheet_01_State');

var obj = {dialog.object}.getControl('myspreadsheetcontrol_1');

obj.setColumnState(json)

 

 

 

UX Component - Client-side Events - onWatchEvent - A new client-side event has been added. The onWatchEvent fires when any of the client-side watch events (show/hide, enable, readOnly) fires. For example, when a client-side show/hide expression on a control is executed the event is fired. The type of event, the name of the control on which the expression is being evaluated and the result of the expression are passed into the event handler.

Possible values for the type parameter passed to the event handler are

 

 

UX Component - Set Tab Order - By default, the tab order in a UX component is the same as the order in which the controls were defined. However, you can now define a custom tab order without having to reorder the controls in the builder.

 

To open Tab Order dialog, select the Set tab order... menu item in the dropdown Menu

 

 

 

 

In the dialog, select the tab order that you want.

 

 

 

UX Component - List Control - Event - onBeforeListClear - Fires before the list data is cleared.

 

UX Component - Client-side Events - canAjaxCallback and onAjaxCallbackComplete - callbackId Parameter - A new parameter is available in the e object passed to these events. The e.callbackId property is a GUID that identifies the callback and allows you to match the onAjaxCallbackComplete event with a particular AjaxCallback.

UX Component - List Control - .setDisplay() Method - This method has been enhanced and can now be used to operate on List columns.

For example, the following method will hide columns 0, 1 and 2 in a columnar List layout:

 

var lObj = {dialog.object}.getControl('list1');

lObj.setDisplay('column',{column: [0,1,2], display: [false,false,false]})

 

 

Documentation - List Control - The documentation system now contains in-depth description of the List object. Note that in the documentation the List is referenced as ListBox, its official internal name.

NOTE: The documentation referenced here does not include the List control methods that are only available when the List has a Detail View. These methods are currently documented here.

 

PhoneGap Builder : Added support for PhoneGap Build Version cli-7.0.1

PhoneGap Build recently added support for PhoneGap 7.0.1 which aside from security and performance enhancements includes some important changes behind the scenes in the build infrastructure. There are now two distinct builders that can be used by PhoneGap Build, the original and the new and this option is exposed in the Alpha PhoneGap App Builder as the PhoneGap Builder Version property, values 1 and 2. By default this value is set to 1 which will use the original builder which will most likely be deprecated at some point in the future. If you set this option to 2, then the new builder will be used by the PhoneGap Build Service.




If you plan to support the new iPhone X, you will need to use storyboard launch images (now supported, see below) and you must use cli-7.0.1 and PhoneGap Builder Version 2.

Please see the PhoneGap Build Blog PhoneGap 7.0.1 Release Notes for all of the details on the cli-7.0.1 release.

PhoneGap Builder: Added support for iOS Storyboards and Android 9 Patch images

With the release of PhoneGap Build cli-7.0.1, support for iOS Launch Storyboards is now inherently supported within the new builder. If you plan to support the new iPhone X or the iPad Pro 12.9’s native resolution or split screen/slide-over multitasking, you’ll need to use iOS storyboard launch images.

Launch storyboard images are sized based on scale, idiom, and size classes. They supports all devices, and can be used with split-screen/slide-over multitasking.




Apple is moving away from legacy launch images. There is no official support for providing a native-resolution launch image for the iPad Pro 12.9 or for providing launch images that work with split-screen multitasking or slide-over. If your app doesn't need to support these contexts, then you can continue to use legacy launch images for as long as you like.

The preferred method of providing launch images is to use a launch storyboard.

These are similar to the legacy launch images, but there are crucial differences:



Designing launch storyboard images (Applies to Android 9-patch images as well)

The key to designing a launch storyboard image is understanding that the edges of the image will almost certainly be cropped. Therefore, one should not place any important information near the edges of any images provided to the launch storyboard. Only the center is a safe area, and this all but guarantees that following Apple's advice of presenting an unpopulated user interface will not work well.

Instead, the following tips should enable you to create a launch image that works across a multitude of form factors, viewports, and orientations:



Of the images supplied to the launch storyboard, iOS will choose the image that best matches the device and viewport and render that image.

The Alpha PhoneGap Builder will generate all of the rerquired storyboard images from a single user supplied square 2732px x 2732px (min) png file. The iOS storyboard file is generated from the image specified for the Portrait splash screen.

Changes to the PhoneGap Build config.xml file

The Alpha Anywhere PhoneGap App Builder will automatically remove and replace certain sections of the config xml file that reference legacy splashscreens, storyboards or Android 9-patch images, based on the properties set within the builder. All of the sections are marked with XML comments and those comments need to remain in place. If legacy splashscreens are specified then the sections for the storyboard and Android 9-patch images are removed, but the comment tags are left intact. If storyboards and Android 9-patch images are specified, then the legacy sections are removed.

If you are modifying an older PhoneGap project with a legacy config.xml file (the comment tags we added around April of 2017), these sections will be added to the older config.xml file and a message will be displayed, indicating that an older config.xml file was modified. In this case, you should edit the config.xml file to remove the older legacy splashscreen section, prior to submission to PhoneGap Build.

 

Grid Component - Arguments - Session Variables - Arguments that are bound to session variables are now updated on every Ajax callback. Previously, the argument values were only set when the Grid was initially run.

Xbasic - email_send_sparkpost() Function - SparkPost Options - SparkPost allows you to specify options, such as open_tracking and click_tracking (see SparkPost API documentation).

You can now pass in these options to the email_send_sparkpost() function as shown below:

 

dim ms as p

'xbasic commands to set required properties of mp not shown

ms.options.open_tracking = .f.
ms.options.click_tracking = .f.
dim key as c = "your sparkpostkey"

dim pp as p
pp = email_send_sparkpost(key,ms)

 

UX Component - DropdownBox Controls - Client-side Data Cache - DropdownBox Box controls can now be populated with data that is stored in the Client-side Data Cache.

This is particularly useful in the case of mobile applications that are deployed as PhoneGap applications, or in static HTML applications that use the Application Cache, because in these applications the DropdownBox controls are populated with data at the time the application in built. When the applications are run, the DropdownBox controls will still continue to show the data that they were populated with at build-time.

In many cases it will be desirable to update the choices shown in a DropdownBox with up-to-date data and to continue to use the most up-to-date data available when the App is launched, even if there is no connection available at that time.
To solve this problem, you can populate DropdownBox controls with data from the Client-side Data Cache.

In order to indicate that data from the Client-side Data Cache should be used, set the first line of the static choices to this:


client-side-data-cache:cacheItemName(displayDataColumn,storedValueColumn)


When the App is launched, if a connection is available, the Client-side Data Cache will be refreshed and the DropdownBox will be populated with fresh data. If no connection is available the first time the App is launched the choices you specify in the second and subsequent lines of the defined Static choices will be used.

For example, assume you had a Client-side Data Cache item called Products and that this item had two columns, Description and Code. In order to populate the DropdownBox to use the Description field as the display value and the Code field as the stored value, you would use this directive in the first line of the Static Choices:


client-side-data-cache:Products(Description,Code)


If you want the display value and stored value to be the same, then just specify the name of the display value column for the stored value.

 

client-side-data-cache:itemName(displayColumn,storedValueColumn)

 

The image below shows how the choices in a DropdownBox control would be defined to read the data from a Client-side Data Cache item called weekdays.

The choices shown starting on line two are the fallback choices that will be used if there is no connection available the first time the App is launched (which means that the Client-side Data cache cannot be populated).

 

 

 

Xdialog - Dynamic Titles - It is now easier to dynamically change the title on an Xdialog. The {title} directive can now display the value of a variable. When the value in the variable changes, the Xdialog title is also changed.

To specify that the {title} directive should use a variable, use this syntax:

{title=@variable_name}

 

 

Example:

 

dim dyn_title as c = "The Title"
ui_dlg_box("dynamicTitleExample",<<%dlg%
{title=@dyn_title};
Title [.80dyn_title!change];
{line=1};
{justify=right}<&Ok>
%dlg%,<<%code%
if a_dlg_button = "change" then
    a_dlg_button = ""
end if
%code%)

 

Clone Workspace - You can now clone a Workspace. The Clone Workspace command is on the File menu when the Web Control Panel or the standard Control Panel have focus.

 

 

UX Component - Slider Controls - Client-side Data Cache - You can now set the data in a slider control based on data in a Client-side Data Cache item.

 

UX Component - Client-side Events - afterControlBasedOnClientSideDataCacheRefreshed Event - Several control types (e.g. SpinList, ButtonList, Slider) can be populated from data in a Client-side Data cache. This event fires after a control that is populated from a client-side data cache item has been populated.

 

UX Component - Expanding Menu Control - Define Menu Choices Using JSON - You can now define the menu choices in an expanding menu control by defining a JSON object.

 

 

Xbasic - Handlebars.js Templating Library - You can now use the popular Handlebars.JS templating library in Xbasic code.

 

NOTE: The Alpha Anywhere templating library is also available to Xbasic code through the a5_merge_JSON_into_template() Function.

 

Example:

dim hb as nodeservices::handlebars

dim source as c = <<%str%
<p>Hello, my name is {{name}}. I am from {{hometown}}. I have
{{kids.length}} kids:</p>
<ul>

{{#kids}}

    <li>{{name}} is {{age}}</li>

{{/kids}}

</ul>
%str%
 

dim json as c = <<%str%
{
    "name": "Alan",
    "hometown": "Somewhere, TX",
    "kids": [

        { "name": "Jimmy", "age": "12" },

        { "name": "Sally", "age": "4" }

    ]   
}
%str%

html = hb.RunTemplate(source,json)

 

Resulting text:

 

<p>Hello, my name is Alan. I am from Somewhere, TX. I have
2 kids:</p>
<ul>

    <li>Jimmy is 12</li>

    <li>Sally is 4</li>

</ul>
 

 

 

UX Component - SpinList and ButtonList Controls - Client-side Data Cache - You can now specify that the data source for a SpinList or ButtonList control is a Client-side Data Cache item. This is particularly useful in PhoneGap applications that are designed to work offline. Here is why:

Say you build a UX component that has a SpinList control and you specify that the control should be populated with data from a Data Series. At the time your PhoneGap application is built, the SpinList with be populated with the data in the Data Series.

Once the PhoneGap app is installed on a device, the SpinList will continue to have the data that was in the Data Series at the time the PhoneGap app was built. If you refresh the Data Series the SpinList will now have up to date data, but this data has not been persisted on the device. So, this means that if you exit the App and re-launch it you are back to having stale data in the SpinList. If you do not have a connection you would not be able to make a callback to the server to refresh the data in the SpinList.

However, if you specify that the SpinList is populated from data in a Client-side Data Cache, the Client-side Data cache will be refreshed automatically when the App is launched and then the SpinList will be populated with the up-to-date data. The data that was retrieved from the server will be persisted on the device (assuming the Client-side Data Cache item was configured to persist data on the device). This means that if you exit the App and then re-launch it (while no connection is available), the SpinList will be populated with the data that was fetched from the server the previous time the App was launched (presuming that at that time a connection to the server was available).

 

UX Component - List Control - Search Part - Server-side After Search Expression Computed Event - New server-side event when performing a search on a List using the List's Search Part.

 

The Grid component exposes a server side event, onSearchPartFilterCompute, that allows developers to override the filter that was computed from the submitted search data. This event fires before the actual search query is executed.

 

Analogous behavior can now be added to searches performed from the Search Part of a List control.

The Javascript method to invoke a search is as follows:

{dialog.object}.getControl('name_of_your_list').searchList( searchOptions)

 

where searchOptions is a JSON object with these properties:

 

For example:

{dialog.object}.getControl('LIST1').searchList({searchMode : 'auto', xbasicAfterFilterCompute : 'xbmodifysearch'});

 

 

 

The Xbasic function takes e as an input parameter.

The e object contains:

e.searchDefinition contains these properties

 searchValue|||field type|argument name

For example:

%UK%|||C|search_country_country1

 

For example:

(Country LIKE :SEARCH_Country_Country1)
 

 

Your Xbasic function can modify any of the properties in the e.searchDefinition object.

 

Bugs

UX Components - Alignment Containers - Client-side Show/Hide Expressions - Were not working on alignment containers.

UX Component - List Control - Star Rating and Switch Control - Client-side Sorting - When you set the control type for a column in a List to either a Star Rating or Switch control and the List had a client-side sort applied to the data, the controls did not behave correctly.

UX Component - Javascript Injection Attack - In some cases, the UX was incorrectly reporting that a Javascript Injection Attack had been detected.

 

Alpha Anywhere V4.5.0 - Build 4584_4961 13-Sep-2017

Bugs

UX Component - List Control - Deleting Records - Under some circumstances a Javascript error was thrown when deleting a List row.

Application Server - IIS - Built-in icons were not displaying a disabled when they should have been.

Alpha Anywhere V4.5.0 - Build 4582_4960 12-Sep-2017

 

 

Videos

UX Component Multi-Lingual PhoneGap Applications Normally, UX components can be localized by wrapping the strings you want to translate in either language tags (<a5:r>...</a5:r>) or text dictionary tags (<a5:t>...</a5:t>). The string translation takes place on the server when the component is rendered. But in a PhoneGap application, the component is loaded from the file system on the device and so you can't use language or text dictionary tags. Instead, you must use a client-side approach (using Javascript) to translate the strings into the selected language.

In this video we show how you can implement client-side language translation.

Watch Video - Part 1
Watch Video - Part 2

Download component

Date added: 2017-08-04
UX Component - FormView Control Client-side Show/Hide and Enable Expressions that Reference External Data Typically, the client-side show/hide and enable expressions in a FormView layout reference field values that are in the data being displayed in the Form. For example, the Form might have a field called Country and you might want to show a container only when the Country field has a certain value.

However, there are also use cases where you want to reference external data (i.e. the value in some other control on the UX) in a client-side expression. This video shows how this is done using FormView state variables.

Watch Video - Part 1
Watch Video - Part 2

Download component

Date added: 2017-08-14
UX Component - ViewBox Control Client-side Show/Hide Expressions that Reference External Data When you define the layout for a ViewBox control, the template can use the {*if} directive to conditionally show/hide content in the ViewBox. Typically the expression in the {*if} directive will reference data in the ViewBox data. But in some cases you might want to reference data that is external to the ViewBox (for example, your UX might have a control whose value you want to reference in the {*if} directive's conditional expression). In order to do this, you must create a ViewBox state variable that is set to the value of the external data.

In this video we show how external data is used in a ViewBox conditional expression.

Watch Video

Download component

Date added: 2017-08-15
UX Component - List Control Displaying Data in a List using a StarRating Control Many applications allow you to rate something by tapping on a star in a StarRating control. The UX component has a stand-alone StarRating control (accessed by selecting [More...] in the UX Builder Controls toolbox), but in some cases you might want to display data in a List control using a StarRating control.

In this video we show how this is easily done.

Watch Video

Download component

Date added: 2017-08-18
UX Component - List Control Row Drag Actions A common user interface pattern seen in mobile apps that use a List is to allow the user to drag on a row in the List to invoke some type of action. For example in the iOS Email app a user can drag on a row to archive the row, mark is as unread/read, or move the row to another folder.

In this video we show how you can implementing row drag behavior an a List control.

Watch Video - Part 1
Watch Video - Part 2

Download component

Date added: 2017-08-25
UX Component - List Control Reorder List Rows by Dragging Row to New Position In certain applications where a List control is used, it is necessary to allow the user to reorder the rows in the List. A common user interface pattern used to reorder List rows is to allow the user to drag a row to its new position in the List.

In this video we show how you can add 'drag to move row' behavior to a List control.

Watch Video - Part 1
Watch Video - Part 2

Download component

Date added: 2017-08-28
UX Component - List Control Displaying Summary Values in Column Footers In some applications you might want to compute summary values (e.g. count, total, average, etc.) for data in a List column and then display that data below the last row of data in that column.

In this video we show how this is done.

Watch Video

Download component

Date added: 2017-09-02
UX Component Adding Keyboard Shortcuts to a Component In this video we show how you can add support for keyboard shortcuts to a UX component. Keyboard shortcuts can speed up a user's interaction with a component. For example, you could configure the Ctrl-S key as a shortcut for saving the data in the a UX.

Watch Video

Download component

Date added: 2017-09-02
UX Component Using the Enter key as a Keyboard Shortcut to Navigate to Next Control For users filling in a UX with many controls, pressing the Enter key to navigate from field to field, can be a useful productivity boost.

In this video we show how the Keyboard Shortcuts feature in the UX component can be used to map the Enter key to navigate between input controls.

Watch Video

Download component

Date added: 2017-09-02
UX Component - List Control Displaying Data in a List using Switch, Radio Button, Checkbox, Integer Increment and Map Controls The UX offers several different control types that can be used to display data in the List.

In this video we demonstrate several of the control types that can be used in a List.

Watch Video

Download component

Date added: 2017-09-02
     

 

 

 

Features

UX Component - Client-side Data Cache - A new option to automatically refresh the Client-side Data Cache before reading it has been added to the following actions in the Client-side Data Cache action in Action Javascript:

When you read the value in a client-side data cache item that has been persisted to storage on a device (either local storage or the file system if in a PhoneGap application), the existing value in the cache will be returned. If you wanted to ensure that you were getting 'fresh' data you would need to first execute an action to refresh the Data Cache. Now you can combine the refresh and read actions into a single step. Both the 'Read Data' and 'Read Multiple Data Items' actions now have a new property - Refresh cache items (if on-line) before read.  When you read an item, the cache will first be updated (if the device is on-line and the Alpha Anywhere server is available) and then the refreshed cache will be read. If the device is not on-line, or the Alpha Anywhere server is not available), then the existing data in the cache is read and returned.

 

 

 

 

UX Component - Client-side Data Cache - Client-Side Data Cache Action in Action Javascript - The Refresh Data Item(s) action now allows you to specify Javascript to handle these situations:

 

 

 

 

Web Control Panel - Bulk Operations UX Components - The bulk operations 'Recalculate UX components' and 'Turn Pre-render option on for UX Components' have been replaced with a new single genie for updating UX components. It is listed in the Web Control Panel menu option Edit -> Bulk Operation as 'Update UX components'

This new genie has options to filter the list of components by filtering by the 'pre-render' property, the file save type (binary or JSON), and if the component was last saved in an older build. This can make selecting the components to update easier. The update options include the original recalculate option and a new option to recalculate all controls as part of the update. Selected components can be changed to pre-render or have the pre-render option removed. The component save format (binary or JSON) can be changed at the same time. The genie includes help to explain the various options.

Some update options will automatically change the filters to show appropriate components. For example, if you select to change components to 'pre-render', only components that are not already pre-rendered will be shown.

Web Security - Using SQL Data - Use DataLink File - A new option has been added to the web security settings when using SQL based tables. A special encrypted single DataLink file is used to store all of the connection data needed to connect to the defined back-end SQL security tables. This file is named 'DataLink.SecuritySettings' and will always be included in every publish with other security settings files. Active Link tables for security are not used with this option and will be removed from the web project when the 'Use DataLink File' option is selected. If the DataLink option is not selected or removed, the original Active Link tables will be recreated as required.

When a DataLink file has been published, the original security Active Link files named 'websecurity_*.*' will not be used and can can be deleted from the published web project. A published application will always use the DataLink.SecuritySettings file if it exists.

 

UX Component - List Control - New Control Types - Several new control types are now available for displaying data in a List. These are:

The images below show the various control types.

 

Watch Video

Download component

 

To select any of the above List Column control types, go to the Fields tab in the List builder and click the smart field for the Control type property.

 

 

 

 

UX Component - Keyboard Shortcuts - You can now define keyboard shortcuts for a UX component.  The shortcuts can run Javascript Actions, click a button, or execute arbitrary Javascript code.

 

Watch Video
Download component
 

To define Keyboard shortcuts, click the smart field for the Keyboard shortcuts property in the UX builder.

 

 

This will open up the genie where you can define key combinations and the corresponding action for the key combination.

 

 

 

 

UX Component List Control - Columnar Layouts - Column Footer - You can now define footers for columns in a List control.

 

 

 

 

 

The ability to define column footers is particularly useful when you want to display summary data (such as totals, averages, etc.) at the bottom of a column of data.

For example, in the image below the total for the Quantity column is shown in column footer for the Quantity column.

 

Watch Video

Download component
 

 

In the above example, the total was added to the column footer for the Quantity column as follows:

 

1. On the Fields tab of the List builder, the Compute summary values option for the Quantity field was checked. This option computes the summary values on the client-side (after the List has been rendered)

 

 

 

2. The following HTML markup was added to the Column Footer Template for the Quantity column:

 

<div>
Total: <span id="{dialog.componentName}.{dialog.listid}.QTY.TOTAL"></span>
</div>

 

3. The following code was added to the afterClientSideSummaryCompute event. The code writes the value for the Quantity total to the element with the id of {dialog.componentName}.{dialog.listid}.QTY.TOTAL. This element was placed in the footer template for the Quantity column. By using the placeholders, {dialog.componentName} and {dialog.listid} in the id, we ensure that the Id is unique.

 

 

UX Component - List Control - Template Commands - New directives are available for use in the List template. These are:

 

 

 

 

Request Enhancements - A new option on the Help menu allows you send enhancement requests to the Alpha Anywhere development team.

 

 

UX Component - List Control - Reorder Rows by Dragging on Row - You can now easily implement a pattern where the user drags a row in a List to a new position.

 

Watch Video - Part 1
Watch Video - Part 2

Download component

 

 

 

To turn on drag-reorder behavior, open the list builder and check the Has row drag reorder behavior property in the List builder on the List Properties pane.

 

 

Then open the settings builder.

 

 

The builder allows you to specify two different modes of operation, DownHold and Handle.

In the DownHold mode, the user presses and holds on the row to be moved. The List then switches to reorder mode and the user can drag the row to its new location.

In Handle mode, the user simply drags on a portion of the row that has been designated as the drag handle to drag a row to its new location. Dragging on any other portion of the row simply scrolls the List. Typically a icon is used to designate the drag handle, and the icon is hidden until the user puts the List in reorder mode (using some Javascript).

When you click the smart field for the Mode option, a dialog is displayed explaining the modes.

Notice when you select the Handle option, a hyperlink is displayed that will show sample HTML, CSS and Javascript to hide the drag handle until the user explicitly puts the List into reorder mode.

 

 

UX Component - List Template Items - You can now display a tab in the List Builder for List template items. Previously you had to open a modal dialog window when you wanted to define or edit List template items.

NOTE: List template items are inserted into a List template using the a5-item attribute in the HTML markup for the List.

 

 

 

You can control the visibility of the Template Items, CSS and Javascript tabs by checking the appropriate checkboxes at the bottom of the List builder screen. If your List definition contains control CSS , items, or user-defined List methods (Javascript), the appropriate tabs are automatically displayed when the List builder is first opened.

 

 

UX Component - List Control - CSS - Control Level CSS - You can now define CSS for a List control. This CSS is scoped to the List.

This means that if you have two List controls on a UX and in the first List control you define a CSS selector called .myclass1 as color:red; and in the second List control you define a CSS selector also called .myclass1 as color:blue; the CSS selector defined in the second List will not override the selector defined in the first List.

The List builder now has a new pane where you can define this control level CSS.

NOTE:  The advantage of CSS defined at the Control level (besides the fact that it is in its own namespace) is that the List is fully defined in the List definition. It does not rely on any CSS classes that are in linked CSS stylesheets or in local (to the UX component) CSS definitions. If you copy the List from one component to another, it will still render correctly.

You can use SASS syntax when defining the control CSS.

 

 

UX Component - List Control - Drag on Row - You can now add support for drag actions on a row in a List. You can define actions for both left-to-right and right-to-left drag actions. For each drag action you can define one or more buttons that are revealed as the user begins dragging on a row.

 

Watch Video - Part 1
Watch Video - Part 2

Download component

 

 

 

The sequence of images shown below shows a List with both left-to-right and right-to-left drag actions defined in its different states.

 

This image shows the list with the first row selected and before user has dragged in either direction on the row.

 

This image shows the List after user begins dragging from left-to-right. Notice that the action button is partially revealed because the user has not dragged sufficiently far to the right.

 

The user has now dragged sufficiently far to the right and has released her finger from the screen. The action button is now locked in place. User can invoke the action by tapping on the button.

 

The user can continue dragging to the right past the specified threshold distance. The action button keeps on expanding in size. If the user removes her finger from the row the action will automatically be selected. User does not have to tap on the button to select the action.

 

 

In this image the user has previously selected the Unread action to mark the status on the row to read. Now the user has dragged again all the way to the right and the label on the action button has changed from Unread to Read. Releasing on the row will invoke the action and mark the row as read. If, instead of releasing, the user drags back in the opposite direction (toward the left), the action button will gradually be hidden and the action will not be invoked

 

This List is shown in its normal state after the user has selected the Unread action. Notice that the icon on the row has changed to indicate that the row has been read.

 

 

The user now starts dragging from right-to-left. Three action buttons have been defined for this action. The action buttons are only partially shown because the user has not dragged sufficiently far. If the user were to release now, the action buttons would be hidden and no action would be invoked.

 

The user has now dragged sufficiently far to the right to fully reveal the three action buttons. If the user releases now the action buttons remain visible in the row. Tapping on one of the buttons will invoke the action. Tapping in the area to the right of the buttons will not invoke any action and the List row will be returned to is normal state.

 

If the user continues dragging on the row (past the threshold distance) after all of the action buttons are fully revealed, the outermost action button (Archive) is auto selected and it begins to fill the row. If the user releases now the Archive action will automatically be invoked.

 

To define row drag settings open the List builder and check the Has custom row drag behavior property on the List Properties pane.

 

 

Then open the genie by clicking on the smart field for the Row drag settings property.

 

TiP: You can get to the Row drag settings genie more quickly by clicking the Quick Access... button at the bottom of the List builder and then selecting Row drag settings from the menu.

 

The List Row Action Builder genie is shown below. The builder has two panes. The Action Buttons pane is where you define the action buttons for the drag actions. The Actions pane is where you define the Javascript code to execute when each action button is selected.

 

 

NOTE: When you drag on a row and select an action, the row you dragged on does not automatically become the selected row in the List. If a previous row was selected, this row remains selected. If you want the row you drag on to automatically be selected, add this code to the Javascript for the Action:

this.setValue(index);

 

 

UX Component - List Control - Lazy Image Loading - Virtualized List - The code that the genie generates has been changed so that if your list is virtualized and you scroll back to a page of List records that have previously loaded images, the spinner will not be shown for the previously fetched images.

 

UX Component - List Control - Star Rating - You can now display data in a List column using a StarRating control. Tapping on one of the stars in the control will update the value in the List.

 

Watch Video
Download component

 

For example, in the image below, the selected row in the List (which has an associated Detail View) was edited by tapping on a star and the List row is shown as dirty.

 

 

To display data in a List column using a Star control, set the Control type for that field to StarRating in the List builder Fields tab (as shown below).

 

 

 

UX Component - Color Picker - A new color picker is now being used in selected parts of the UX builder.

The color picker has several modes that make selecting colors easier and faster.

The color picker also has support for semi transparent colors (when set into either 'rgba', 'hsla' mode).

In the image below, the 'Fan Decks' (like paint swatch sheets that you get from a paint store) allows you to select from a series of predefined colors.

On the left you can select any color and transparency that you want by dragging the sliders.

The selected color is shown in the rectangle at the top left.

In the top right corner of this rectangle a much smaller square is shown. This is the color that was originally selected when the color picker was first opened. It allows you to quickly switch back to the initial color by clicking on the color square.

 

 

In the Palettes mode (shown below) you can select from a palette of pre-defined colors that you define.

 

You can easily add a new color to the palette by selecting a color in the left hand pane and then clicking the + icon in the Palettes pane.

Another way to add a color to the palette (when the Palettes mode is not selected) is by clicking on the

button in the left hand pane.

You can manage your palettes by clicking the down arrow icon in the Palettes mode

 

 

 

In the Image mode (shown below) you can load an image into the image picker and then select colors by pointing to different parts of the image.

 

 

You can set the mode in which the color picker works by clicking on the button (shown as HEX in the above image)

This brings up a menu showing the mode.

 

 

UX Component - Star Rating Control - Color of Un-selected Stars - You can now set the color of un-selected stars as show in the images below. The top image shows the current default color and in the second image both the selected and un-selected colors have been changed.

TIP: The Star Rating Control is selected by selecting the [More...] item in the UX toolbox (in the Data Controls section).

 

 

Application Server for IIS - Publishing  - IIS publish now supports optimized publishing (like all other publishing types when using the standard server). Previously, when you published to IIS all of the files in your project were automatically published. It was not possible to publish a single file, of a selected subset of files, as is possible when publishing to the Alpha Anywhere server.

When you publish to IIS, a staging folder named __staging.staging is now located in the web project folder. This folder will contain the published application in a form ready to be deployed to an IIS server.
 

Application Server for IIS - Page Security - Deny by Default -  Authorization is now denied by default under IIS. The authorization rules for accessing files under IIS were previously set on files only known at publish time. This meant that files could be added to the web root of a published application and access would be allowed to any of these files. This changes means that a file needs to have a rule set to expressly allow or allow by group name in order for it to be accessible in an application.
 

Grid Component - Detailed Javascript Error Reporting - In V4.5 detailed Javascript error reporting was added to the Grid. This was done by defining a handler for the window.onerror event. This has caused error alerts to be displayed even when the Javascript errors are benign and caused no problem with the Grids that were run in prior versions. Now, detailed Javascript error reporting is off by default, but you can turn it on using this property:

 

UX Component - PhoneGap - Action Javascript - Open File with Native Application -- SQL Server Reporting Services - This action can now work with SSRS reports.

 

 

UX Component - Data Driven Forms Sample Template - The sample template showing how to create a data-driven form (first released in v4.5) has been updated to include a star-rating control.

 

 

 

UX Copmponet - FormView Control - Action Javascript - The Action Javascript action for FormView actions now has two additional actions:

 

State variables can be referenced in the FormView layout templates (and therefore in client-side show/hide and enable expressions) using this syntax

[temp].state.your_variable_name

 

Say you had a container in a FormView layout that contained several controls. You wanted to show this container if a session variable (called say myVar1) was equal to 'alpha'.

MOTE: You would, of course, need to publish the value of this session variable to the client-side by setting the Published session variables property.

 

Here is how you would do this:

Set the show/hide expression for the container to

[temp].state.myVar1 == 'alpha'

 

In the client-side onRenderComplete event, execute this code to set the FormView control's myVar1 state variable to the value of the session variable.

 

var myVar1 = {dialog.Object}.getSessionVariable('MYVAR1');

{dialog.object}.formViewSetStateVariables('FORMVIEW_1',{myVar1: myVar1});

 

 

Watch Video - Part 1
Watch Video - Part 2

Download component

 

UX Component - Audio Player/Recorder Control - New Events - Two new events have been added to the Audio Player/Recorder

 

 

 

 

UX Component - window.onerror Event Handler - In V4.5, the UX component generates a widow.onerror event handler to report Javascript errors. This event handler displays an alert with a full stack. In some cases, where you are loading 3rd party Javascript libraries, that might throw benign errors on loading, you might want to suppress this error reporting.

The Capture detailed Javascript error information property allows you to turn off detailed Javascript error reporting.
 

 

 

UX Component - Templates - Localize PhoneGap Application - A new template is available showing how you can localize a PhoneGap application at run-time, allowing the user to select the language used for the app. The template is called MobileAppFramework_Client-side-Language_Translation.
 

Watch Video - Part 1
Watch Video - Part 2

Download component

 

UX Component - Templates - SecurityFramework-LoginComponentMobileApp-Persistent Login - The template showing how to build a mobile app that has a persistent login has been updated. The template now applies security settings when the component is reloaded and a persistent login token is found.

Alpha Anywhere Application Server for IIS - Publish - Delete Files - Publish to IIS no longer deletes files and folders that are not part of the web project. This applies to existing publish profiles and new publish profiles. Previously, any files in the target webroot folder that were not part of the web project were deleted when a project was published.

In the event a you want the old delete behavior, the Delete existing files option can be checked in the publish profile:

 

or the Delete existing files option can be checked in the Advanced Settings section when creating a new publish profile:

 

 

 

UX Component - Pre-Defined Date Range Selector Control - The Date Range selector control is useful if your UX component has controls where the user must enter a start date and an end date.

In the image below, the Date Range Selector (a dropdown box) shows the list of date ranges. The user has selected the 'This Year-to-date' range and the two input controls (one for date start, the other for date end) have been filled in.

 

 

To add a Date Range Selector control to your UX, select the control from the Defined Controls section of the UX toolbox.

 

 

Once you have added the control, you must edit the Javascript in the control's onChange event to define the Ids of the start and end date controls.

 

The Choices property for the Date Range Selector shows these choices. These are the built in options. You can add text or language tags to the display value if you want to show the choices in a different language.

 

|
Today|today
Yesterday|yesterday
This Week|thisweek
This Week-to-date|thisweektodate
This Month|thismonth
This Month-to-date|thismonthtodate
Last Week|lastweek
Last Month|lastmonth
Next Month|nextmonth
This Year|thisyear
This Year-to-date|thisyeartodate
This Quarter|thisquarter
This Quarter-to-date|thisquartertodate
Last Quarter|lastquarter
Next Quarter|nextquarter

 

You can also add your own custom choices to this List. When you define a custom choice you use this syntax

Display value|javascript:javascript code to compute start and end date

 

The Javascript code that you write must follow these rules:

For example, here is how a customer item called 'Tomorrow' could be added to the choices in the Date Range Selector Control:

 

(Code shown on multiple lines for clarity. Must all be on a single line)


Tomorrow|javascript:/*custom date range. code must not contain any commas*/var d1 = new Date(); var d2 = new Date(); d1.setDate(d1.getDate() + 1); d2.setDate(d2.getDate() + 1); var obj = {}; obj.startDate = d1; obj.endDate = d2; return obj;

 

 

Xdialog - Overlays - You can now design Xdialogs with floating 'overlay' windows. The overlays are similar to bubble-help that you can define for toolbar buttons, Xdialog buttons, etc. except that the overlay content can be any HTML text and the overlay can be applied to any part of the Xdialog.

 

In the images below an overlay is shown when the mouse if over the combo box and another overlay is shown when the mouse is over the button.

 

 

The Xdialog {overlay=variableName} directive is used to define an overlay.

 

Here is the code to produce the above Xdialog.

 

dim overlay1.html as c = <<%html%
<div style="margin: 0px; padding: 5px; border: 1px blue solid; border-radius:10px;">
This <b>combo</b> lets you pick a number on entries<br>
Your choices are one, two, three or four.
</div>
%html%

dim overlay2.html as c = <<%html%
This is the button that performs the action
%html%

dim item as c = "one"

ui_dlg_box("with_help",<<%dlg%
A Combo;
List {overlay=overlay1}[.60item^={one,two,three,four}];
{line=1};
{overlay=overlay2}
<&Do It...>
%dlg%)

 

UX Control - Multi-select Tokens Control - Text Highlighting - When you start typing into a multi-select tokens control, the list of choices that is displayed, which is filtered, by the text you have typed, now shows the matches in the choice list with the text you have typed in bold.

 

For example, in the image below, the user has typed an 'a' and the choice list shows all of the items that contain an 'a'. Notice that in the choice list all of the 'a' characters are bolded.

 

If you have an existing multi-select token control you will need to edit and resave to get this feature.

ViewBox and FormView Control - Post-process event - You can now specify post process Javascript for each Layout. The post process Javascript runs after the HTML for the layout has been rendered. You can use the Post-process event to modify the HTML that is shown in the layout. A common use of this event is using the A5.u.html.highlight() function to highlight some text in the Layout html.

Javascript Library - A5.u.html.highlight() Function - Can be used to add markup to an HTML string to highlight portions of the text in the HTML. Any text in HTML elements or attributes is ignored.

Syntax:

A5.u.html.highlight(html, searchString [, prefix [,suffix]])

Where

 

Example

var html = '<div>this is some text</div>';
var html2 = A5.u.html.highlight(html,'ome')
 

The resulting html2 string will be:


<div>this is s<b>ome</b> text</div>

 

Example using a function for the prefix argument:

 

count = 0;

var html = '<span>this text is inside a span. But only a single span</span>'

A5.u.html.highlight(html,'span',function(search,match,offset,html){
    count++;
    return '<i id="match.'+count+'">'+match+'</i>';
    }

)

Result

<span>this text is inside a <i id="match.1">span</i>. But only a single <i id="match.2">span</i></span>
 

 

Grid Component - Pre-defined Date Ranges - When you define the Search Part for a Grid, you can specify that any of the search fields are 'range' searches. If you turn on the range search feature, the Search Part will display two search fields for the start date and the end data.

You can now also display an optional pick list to select common date ranges, as shown in the image below. If you select one of the pre-defined date ranges, the dates in the From and To input controls will be filled in.

 

 

 

To turn on the pre-defined data range feature, check the Pre-defined date range selector property.

 

 

You can then click the smart field for the Pre-defined date range selector settings control to configure the selector.

The settings dialog allows you to set:

 

By default a standard set of pre-defined date ranges are shown. These are:

 

If you want to translate these names into different languages you can customize the list of choices and add language or text dictionary tags to each label.

You can augment this list with your own data ranges, or you can replace the built-in list with your own date ranges.

To define your own entry to appear in the list of choices, add a choices to the choice list that is defined as follows:

display name in the selector|value|javascript

 

where value is a unique name for the selection. The value must not contain any special characters or spaces. Javascript is some code that returns an object with two properties: startDate and endDate.

 

For example:

 

a5_ink_to_png() Function - This function now has a new parameter that lets you control how the image is created from the ink. Previously, the image was bound to the size of the ink with a 20px border. Now you can size the image to the entire ink page, not just the bounds of the ink text.

The new optional parameter is flagUseViewBox. This defaults to .f. (size the image to the bound of the ink). Set to .t. to size the image to the entire ink page.

Syntax:

a5_ink_to_png(c ink ,n heightInPoints,n widthInPoints,c filename ,l   flagUseViewBox)
 

Bugs

Code editor - Code Library - The code Library got broken in a recent release. This is now fixed.

Javascript Errors - The previous build was too aggressive in reporting Javascript errors. Benign Javascript errors are no longer reported.

PhoneGap - SQLite - MySQL - Bit(1) Columns - A bug in creating a SQLite database from a MySQL database when a table in the MySQL database has bit(1) columns has been fixed. Alpha Anywhere treats bit(1) columns as Logical columns. So a value of 3 or 4 (for example), are both interpreted as True by Alpha Anywhere.

Tips

UX Component - HTML Editor - Display as Pop-up - Double-click - If you configure an HTML editor to act as a pop-up and you specify that the control has a 'click to edit' button, then you can open the HTML editor by clicking the button. However, double clicking on the HTML control will also open the editor. If you want to disable the double click, so that the HTML editor can only be opened by clicking the button, add this code to the UX onRenderComplete client-side event:

 

var obj = {dialog.object}.getControl('name_of_html_control')
obj.dblClickEdit = false;

 

 

 

Alpha Anywhere V4.4.5 - Build 4491_4932 30-July-2017

 

Videos

UX Component - List Control Lazy Image Loading A common use case for Lazy Image Loading is when you have a List that displays images that are sourced from a server. If the List has a large number of rows, fetching all of the images from the server will slow down the initial render of the List. However, by implementing Lazy Image Loading, only the images for the rows that are currently scrolled into view will be fetched.

You can set a wait time that the List will wait after a row comes into view before the images for the visible rows will be fetched. This prevents fetching images for rows that you scroll past without stopping on. When a row that displays an image that has not yet been fetched is displayed, a 'waiting' image will be displayed. Once the image has been fetched, the 'waiting' image will be replaced with the real image.

In this video we show how to configure a List control to use Lazy Image Loading.


Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Download Component

Date added: 2017-05-25
UX Component - ControlBar Control Dynamically Styling Items on a ControlBar A common requirement when using ControlBars is to dynamically style the items on a ControlBar. For example, you might want some text to be red under one condition and green under another condition.

In this video we show how client side templating directives (e.g. {*if} ...{*endif} can be used to define dynamic styles and classes.

Watch Video

Download Component

Date added: 2017-06-09
UX Component - ControlBar Control Showing a List Control in a ControlBar Disclosure A powerful feature of the ControlBar is its ability to display 'disclosures' (i.e. windows). These disclosures can be animated into view from various positions on the screen. A common requirement is to show a List control in a disclosure.

This video shows how this can be done.

Watch Video - Part 1
Watch Video - Part 2

Download Component

Date added: 2017-06-18
UX Component - FormView Control Review of Different Field Editors Fields in the FormView control are edited using Field Editors. You can build your own Field Editors, or chose from the collection of built-in Field Editors.

In this video we review the different built-in Field Editors that are available as of Build 4192.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Download Component

Date added: 2017-06-25
UX Component - FormView Control Displaying Data from Hierarchical Lists in a FormView Control (This video is aimed at advanced users of the FormView control).
The FormView control can display data from multiple Lists that are linked in an hierarchical relationship. E.g. A Customer List with a child Orders List. By default, when the FormView displays data for a selected row in the parent (i.e. Customer) List, it will display ALL of the data from the children of the selected row. In other words, the FormView control will display data for the selected customer in the Customer List and it will show ALL of the orders for the selected Customer.

However, in some applications, you might want to display only the data for the selected Order in the Orders List. In other words, the FormView control should use BOTH the parent (i.e. Customer) List and the child (i.e. Orders) List as selectors for the data that should be shown in the FormView control.

In this video we show how the FormView control is configured to show just the data from the selected row in the child (i.e. Orders) List.

Note: Another way to achieve this result would have been to use two separate FormView controls - one for the Customer List and one for the Orders List.


Watch Video - Part 1
Watch Video - Part 2


Download Component

Date added: 2017-06-26
UX Component Introduction to Style 'Tweaks' In order to change the appearance of a UX component you can either edit the stylesheet or you can 'tweak' the style.

In this video we show how you can tweak the style to change the colors in the stylesheet and also how you can add a new button sub-theme.

Watch Video

Date added: 2017-07-05
UX Component - FormView Control Displaying Editors in a Pop-up Window The typical pattern in a mobile UX component that uses the FormView control is to place the editors in their own PanelCard that is animated into view when the user taps on a field in the form to edit its value.

However if you are using a FormView control in a web application, you might prefer the editors to be shown in a pop-up window next to the field you are editing.

In this video we show how the editors used in a FormView control can be opened in a drop-down window relative to the form field you are editing.

Watch Video

Download Component

Date added: 2017-07-05
UX Component - List Control Injecting Arbitrary Headers and Footers into List Data You can inject arbitrary HTML into the List. This can be used to add headers and footers into the List as shown in this video.

Watch Video
Download Component
Download Component - collapsible headers

Date added: 2017-07-12
UX Component - Multi-select Tokens Control Adding a Multi-select Tokens Control to a UX Component The Multi-select Tokens control operates much like the Gmail app when you address an e-mail to multiple recipients. You can type values into a control, or make selections from a drop-down choice list. Each selection is shown in the control as a 'token'. Tokens can be removed from the list of selections by either hitting the backspace key while focus is in the control, or by clicking on the 'delete' icon in the token.

A common use case for the Multi-select Tokens control is to define selection criteria for a List control. In this video we show how a Multi-select Tokens control is used to select a list of countries. The List control is then filtered to show the countries that match the selected tokens. For example, if tokens for 'USA' and 'UK' are selected, the List is filtered to show customers in either 'USA' or 'UK'

Watch Video - Part 1
Watch Video - Part 2

Download Component

Date added: 2017-07-23
UX Component Data-driven Forms A data-driven form is a form whose fields are determined at run-time (typically by querying a database) to get a list of the fields to display in the form.

In this video we show how a ViewBox control and an Editor Set with multiple Editors can be used to implement a data driven form.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4

Download component

Date added: 2017-07-26
     

 

 

Security

 

 

Alpha Anywhere Server for IIS - A potential security issue under IIS has been fixed. A UX AJAX request could be crafted to return the content of a file that should not be visible outside of the server. This fix closes this vulnerability.

Features

email_send_sparkPost() Function - Reply To - Support has been added for the 'Reply to' parameter.

 

Example:

dim ms as p
ms.send_to = "Fred@acme.com"
ms.reply_to = "Harry@acme.com"
ms.from_email = "admin@acme.com"
ms.from_alias = "admin@acme.com"
ms.from_name = "Admin" 
ms.subject = "Reply To Now Supported"
ms.message_html = "Message goes here"
dim key as c = "Your api key"
pp = email_send_SparkPost(key,ms)
 

 

Grid Component - Column Sorting - Initial Sort Direction - When the user first clicks on a column to sort the Grid on that column an ascending sort is performed. Now you can specify that the initial sort should be descending.

 

 

UX Component - Minimum Build Number - You can now specify a minimum build number for a UX component. If a developer tries to edit the component using a build that is older than the specified minimum build, a warning will be displayed. The user will not, however, be prevented from editing the component.

 

 

 

 

UX Component - Data Driven Forms Sample Template - A new sample template has been adding showing a technique for implementing data driven forms. A data driven form is a form where the fields in the form are determined at run-time, rather than at design-time.


Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4

Download component

Typically, the form is generated by first querying a database to determine what fields the form should display. Then, some Xbasic code is executed to generate a dynamic form definition.

In the example template the form is implemented using a ViewBox control, an Editor Set and numerous Editors for editing the field values shown in the form.

The image below shows how the sample component renders a particular data-driven form. The actual fields shown in the form are easily controlled by editing a JSON object that defines the fields, the field types and the editor to be used to edit the field value.

 

 

 

 

UX Component - Multi-select Token Control - A new control type is available for the UX component. The Multi-select Token control is similar to the Edit-combo control and the Auto-suggest control. However, the selected values are displayed as 'tokens' (as shown in the image below where 'Belgium', 'Brazil' and 'Canada' are selected).

 

Watch Video - Part 1
Watch Video - Part 2

Download Component

 

 

The user can select values from a pick list as shown in the image below. The pick-list can be automatically displayed when the user starts typing in the input control, or can be displayed when the user clicks on the down array (which is optionally displayed). The user can also select tokens by typing the value into the control and then pressing the Enter key.

To delete a previously selected token, click on the X icon in the token, or click to the right of the last selected token and press the Backspace key.

 

 

The choices for the pick-list can be statically defined, can be derived from querying a SQL database, or can be computed by an Xbasic function.

 

How to Add a Multi-select Token Control to a UX Component

 

To add a Multi-select Token control to your UX component, select the [More...] item in the Data Controls section of the UX toolbox.

 

The Multi-select Token control is a Data Control. This means it has a .getValue() and a .setValue() method, just like other Data Controls. When the UX is submitted, the data in the Multi-select Token control are submitted as a comma delimited list of token values.

For example, if there are three tokens selected with values of 'USA', 'UK' and 'Canada', the value submitted is 'USA,UK,Canada'

To set the value in a Multi-select Token control you must specify an array of values. For example

{dialog.object}.setValue('MY_MULTISELECT_TOKEN_CONTROL',['USA','UK','Canada']);

 

To set a default value for the control in the Default value property in the property sheet you can use this syntax

array(USA,UK,Canada)

 

Setting the Multi-Select Token Control Properties

To set the properties of a Multi-select Token control, click the smart field for the Control properties property in the Property sheet.

The configuration genie window is displayed, as shown below:

 

 

Dynamically Populating Choices at Runtime

You can dynamically populate the choices in the Multi-select Token control at runtime by calling the control's .populate() method. For example, assume you have a Multi-select Token control called 'MST1'. You can use the following Javascript  to populate the control's choices:

 

var _d = {
    "data":[
        {"value" : "Argentina", "display" : "Argentina"},
        {"value" : "Austria", "display" : "Austria"},
        {"value" : "Belgium", "display" : "Belgium"},
        {"value" : "Brazil", "display" : "Brazil"},
        {"value" : "Canada", "display" : "Canada"},
        {"value" : "Denmark", "display" : "Denmark"},
        {"value" : "Finland", "display" : "Finland"},
        {"value" : "France", "display" : "France"},
        {"value" : "Germany", "display" : "Germany"},
        {"value" : "Ireland", "display" : "Ireland"},
        {"value" : "Italy", "display" : "Italy"},
        {"value" : "Mexico", "display" : "Mexico"},
        {"value" : "Norway", "display" : "Norway"},
        {"value" : "Poland", "display" : "Poland"},
        {"value" : "Portugal", "display" : "Portugal"},
        {"value" : "Spain", "display" : "Spain"},
        {"value" : "Sweden", "display" : "Sweden"},
        {"value" : "Switzerland", "display" : "Switzerland"},
        {"value" : "UK", "display" : "UK"},
        {"value" : "USA", "display" : "USA"},
        {"value" : "Venezuela", "display" : "Venezuela"}
    ]
};

var obj = {dialog.object}.getControl('MST1');
obj.populate(_d);

 

Grid Component - Summary Fields - Headers - You can now specify that column headers should be repeated before the summary values are shown (as shown in the image below). This is useful when you have a Grid with a lot of rows and the page must be scrolled to get to see the summary values.

 

To turn on this feature, check the Repeat column headings above summary values property.

 

 

Web Security - Get User Values When Using Active Directory - a5ws_GetUserValuesActiveDirectory()  - A function named a5ws_GetUserValuesActiveDirectory() has been added to Alpha Anywhere.  It can be used in code running on a web server to get user values when using Active Directory for security authentication.  This function works in the Classic Alpha Anywhere server and IIS and retrieves a number of default values from Active Directory.  Help about this function is found in the documentation at 

https://www.alphasoftware.com/documentation/index?search=api%20a5ws%20getuservaluesactivedirectory%20function

 

Xbasic - Arrays - .push() method - A new .push() method has been added for Xbasic arrays. To push onto a property array use JSON syntax to define the object you want to push onto the array. See examples.

 

Examples:

 

dim arr[0] as c
arr.push("hello")
arr.push("world")
? arr
= [1] = "hello"
[2] = "world"
 

'using a property array
dim arrp[0] as p
 

'push object defined using JSON syntax onto the array
arrp.push({"text":"hello"})
arrp.push({"text":"world"})
? arrp.size()
= 2
? arrp[1].text
= "hello"
? arrp[2].text
= "world"

 

 

UX Component - List Control - Inject Arbitrary Headers and Footers into List Data - You can now inject arbitrary headers and footers into List data using the onBeforeListDraw event. For example, in the image below a header is inserted for each group of 3 rows of data. A footer is also inserted. Both the header and footer can contain arbitrary HTML. As shown in the image, the footer text contains some bold text as well as a SVG icon.

Watch Video
Download Component

Using items (i.e. the a5-item attribute), you can add event handlers to the header and footer text (see video).

The onBeforeListDraw event allows you to return a new array containing the data to be rendered in the List.

 

 

In the above example, the following Javascript is defined in the onBeforeListDraw  event to add the headers and footers to the List.

 

var ta = [];
var group = 1;
for(var i = 0; i < data.length; i++) {
    //add a user defined title into the data before every 3rd row
    if( (i % 3 ) == 0) {
        if(i != 0) {

            //add the footer html
            ta.push({'*static': '<div a5-item="item1:'+(group-1)+'" style="padding: 10px; border: solid 1px gray; border-radius: 10px;">

                    <img src="svgIcon=#alpha-icon-basketFull:26{ fill: #2730d1; stroke: #f52d2d;}" />This is some static <b>HTML</b>.

                    It shows how you can add arbitrary HTML into the List</div>'});
        }

        //add the header html
        ta.push({'*title': 'Group ' + group});
        group++
    }
    ta.push(data[i]);

}
//return a new array of data to be used to draw the list
return ta;

 

To inject a header into the List, add an object into the data array that has a '*title' property name. To add arbitrary HTML (e.g. a footer), add an object into the data array that has a '*static' property name.

Notice that in the above Javascript code, the data array is passed in. But the contents of this array are not modified. Instead a new array (called ta) is created and the Javascript returns this array. The List is then rendered using this new array of data.

 

Collapsible Headers

The image below shows a slightly more complex example. In this example, each header is made collapsible. For example, Group1 through Group4 have been collapsed. Tapping anywhere on the header will toggle the collapsed state of the group.

 

Download Component - collapsible headers

 

 

 

The Javascript in the onBeforeListDraw event to accomplish this is shown below:

 

var ta = [];
var group = 1;
var to = this._to;
if(typeof to == 'undefined') to = {};
var flag;
var iconOpen = A5.u.icon.html('svgIcon=#alpha-icon-addCircleBorder:icon,24');
var iconClose = A5.u.icon.html('svgIcon=#alpha-icon-removeCircleBorder:icon,24');;
var icon;
for(var i = 0; i < data.length; i++) {
//add a user defined title into the data before every 3rd row
    if( (i % 3 ) == 0) {
        if(i != 0) {
            if(flag == 'opened') {
                ta.push({'*static': '<div a5-item="item1:'+(group-1)+'" style="padding: 10px; border: solid 1px gray; border-radius: 10px;"><img src="svgIcon=#alpha-icon-basketFull:26{ fill: #2730d1; stroke: #f52d2d;}" />This is some static <b>HTML</b>. It shows how you can add arbitrary HTML into the List</div>'});
            }
        }

        flag = to['Group:' + (group)];
        if(typeof flag == 'undefined') flag = 'opened';
        if(flag == 'opened') icon = iconClose;
        else icon = iconOpen;
        ta.push({'*title': '<div a5-item="toggle:' + group + '" style="line-height: 26px;"><div style="float:right;">'+icon+'</div>Group'     +   group + '</div>' });
        group++
    }

    if(flag == 'opened') {
        ta.push(data[i]);
    }
}
return ta;

 

Notice that the header is wrapped in a div that has an a5-item attribute called toggle. Notice also that the list contains a variable called _to that contains an object with the open/closed state of each group. If a group is closed then the code that pushed the list data onto the new array (ta.push(data[i]) is skipped over, thus omitting these rows from the rendered List.

When a user taps on a header, the onClick event in the toggle item is fired. This event will then add the group's open/closed state to the List object's _to variable. The Javascript code in toggle item's onClick event is shown below:

 

var to = lObj._to;
if(typeof to == 'undefined') to = {};
var flag = to['Group:' + ia];
if(typeof flag == 'undefined') {
    to['Group:' + ia] = 'closed'
} else {
    if(to['Group:' + ia] == 'closed') to['Group:' + ia] = 'opened';
    else to['Group:' + ia] = 'closed';
}
lObj._to = to;
lObj.refresh();

 

UX and Grid Components - Amazon S3 - V4 Signing - Ohio Region - Amazon has changed the way that URLs must be signed for their newer regions. For example, support for the Ohio region was recently added to the Storage Connection String builder. But in order to upload or download files to/from the Ohio region, URLs must be signed using Amazon's V4 signing scheme. Support has been added for V4 signing, so now uploads and downloads to the Ohio region will work correctly.

 

 

UX Component - ExpandingMenu Control - A new control type is available in the UX Component. The Expanding Menu control displays a list of menu choices, some of which may have sub-choices (indicated by an icon at the right edge of the item). When a menu item is clicked, it can invoke Javascript code. If the menu has a sub-menu, the sub-menu is shown using animation.

In the image below the ExpandingMenu is shown in its full collapsed state and it a partially expanded state.

 

 

 

 

To add an ExpandingMenu control to your UX component, select the [More...] item in the Data Controls category.

NOTE The ExpandingMenu is in the Data Controls section, because, like all Data Controls, it has a {dialog.object}.setValue() and a {dialog.object}.getValue() method. The 'value' of the current selection in the Expanding menu is defined by the 'value' property for each node in the tree (see below).

 

 

 

 

Then select the ExpandingMenu option from the dialog.

 

To configure the ExpandingMenu control, click the smart field for the Control properties property.

 

 

 

This will bring up a genie where you can define the choices shown in the ExpandingMenu and also set other properties.

 

 

To define the choices and sub-choices shown in the menu click on the smart field for the Menu data genie property.

This will bring up a dialog where you can type in your menu choices, using tab indents to indicate which menu choices are sub-choices.

For example, in the image below, the top level menu choices are:

item1

item2

item3

item4

 

Item1 and item2 hav3 sub-choices.

 

 

When you close the Add Item dialog, the Tree Data Genie is shown (see image below). This dialog allows you to set properties for each menu item in menu tree.

 

 

Properties that you can set include:

 

Grid Component - Delete Checkbox - Delete All - A new option has been added to the Grid component to allow you to check/uncheck the Delete checkbox in all rows on the current Grid page at once.

To turn on this feature, check the Allow 'delete-all' checkbox property.

Update Settings

 

The Grid will be rendered as shown below. The Delete column title will have a checkbox in it. Checking this box will check the delete checkbox in all Grid rows on the current Grid page.

 

 

UX and Grid Components - Javascript Errors - Error Reporting - Error reporting when a Javascript error occurs has been improved. The error message will now include a stack dump.

 

UX Component - ViewBox Control - Sample ViewBox - When you create a new ViewBox a new sample ViewBox is is now available when you click on the Load Sample ViewBox hyperlink.

 

 

 

 

The Menu tree option displays an hierarchical menu as sown in the image.

 

 

 

UX Component - Sample Templates - MobileAppFramework_with_SplitView_ExpandingTreeMenu - A new sample template for mobile apps is available. This template is similar to the the MobileAppFremework_SplitView_Hierarchical_Menu template, except that the menu is rendered using a ViewBox control, not a List control.

The ViewBox menu can contain nested menus. When a menu item that has children is expanded, the ViewBox is animated, creating a very appealing visual effect.

 

To use the template, chose the template from the list of available templates when you create a new UX component.

 

 

 

On a Phone, the UX will render as shown below.

 

 

Tapping on the 'hamburger' menu icon will show the menu in its collapsed state:

 

 

You can expand various branches of the menu. When you tap on a menu item that is an endpoint, the associated action for that menu item is executed.

 

 

On a tablet, the menu is always shown on the left of the screen.

 

 

To edit the list of choices shown in the menu, edit the ViewBox Control. In the ViewBox control, edit the Data Source. The menu structure and the associated menu actions are defined in the Javascript object for the ViewBox data source.

 

The background color of the menu is set in the CSS tab in the ViewBox builder. To change the menu color, edit the ViewBox and in the CSS tab, edit this value:

 

$color: #221f22; //this sets the color of the menu tree.
 

 

 

Xdialog - Simple List View Control - The simple list view control has been enhanced to allow sortable columns and different views of the data.

 

In the image below, the List has been sorted on the Firstname column and a small icon in the column title indicates the sort direct.

This is the 'report' view of the data.

 

 

In the image below, the 'list' view of the data is shown.

 

 

In the image below, the 'SmallIcon' view of the data is shown.

 

 

To indicate that a column is sortable, add a caret to the column definition. For example:

[%M;K;%.100,20id^"Firstname:30^|Lastname:50^"list!idchange];
 

In the above example, we have defined both the Firstname and Lastname columns to be sortable.

You can specify if the sort should treat the data as numeric or data/time values by adding a suffix of N or T after the ^. For example

[%M;K;%.100,20id^"Lastname:30^|DateOfBirth:50^T"list!idchange];
 

 

To change the view of the List, send a command to the list using the ui_dlg_ctl_command() function, as shown in the example below. The second parameter in the function is any string in the control definition that uniquely identifies it. In the example below, the text string 'idchange' is used to identify the control.

 

You can also sort the List on multiple columns using the ui_dlg_ctl_command() function. For example to sort on Lastname (column 2) and then Firstname (column 1), you this command:

 

 ui_dlg_ctl_command(dlg_title,"idchange","sort:2,1")

 

Full example:

 

dim list as c
list = <<%txt%
{image=$$generic.orb.green}Erica|Jones
{image=$$generic.orb.blue}Tom|Snider
{image=$$generic.orb.yellow}Molly|Maloney
%txt%
list = replicate(list,30)
list = *for_each(x,"{data=" + *index() + "}" + x, list)


dim dlg_title as c = "Quick ListView - Sortable"
ui_dlg_box(dlg_title,<<%dlg%
{wrap=100}
This dialog shows a simple ListView using the new ^" Xdialog syntax.;
Using this technique, it is possible to create a simple ListView with substantialy less Xbasic than the {{Listview} Xdialog command.;
The ^ in the control definition makes the column sortable.;
 

[%M;K;%.100,20id^"Firstname:30^|Lastname:50^"list!idchange];
{lf};
Click button to change List layout;
<List><Report><SmallIcon>
%dlg%,<<%code%
if a_dlg_button = "List" then
    a_dlg_button = ""
    ui_dlg_ctl_command(dlg_title,"idchange","list")
else if a_dlg_button = "report" then
    a_dlg_button = ""
    ui_dlg_ctl_command(dlg_title,"idchange","report")
else if a_dlg_button = "smallicon" then
    a_dlg_button = ""
    ui_dlg_ctl_command(dlg_title,"idchange","SmallIcon")
else if a_dlg_button = "idchange" then
    a_dlg_button = ""
    ui_msg_box("Note","User clicked on : " + id )
end if
%code%)

 

 

 

 

UX Component - FormView Control - Pre-defined Editors - AlphaNumeric KeyPad Editor - A new pre-defined editor for editing character and numeric values in a FormView control (without using the Native keyboard on a mobile device) has been added.

The editor, as shown in the two images below, display the AlphaNumeric KeyPad editor in its two possible configurations. In the first image, the KeyPad is shown as it would be displayed on a Phone.

In the second image, the KeyPad is shown as it would be displayed on a Tablet.

 

 

 

 

 

 

 

To add the editor to a UX component, select the [Editor-AlphaNumericKeyPad] from the Defined Controls section of the toolbox.

 

 

To configure the keypad settings, click the smart field for the Editor configuration genie property in the FormView builder.

 

 

 

The genie allows you to configure various aspects of the keypad.

 

 

UX Component - FormView Control - Pre-defined Editors - Time Value Editor - A new pre-defined editor for editing time values in a FormView control has been added.

The editor, as shown below, displays SpinList controls for the hour, minutes and AM/PM values.

The editor also displays a button to set the selection in the SpinList controls to the current time.

You can configure the editor to hide the 'Now' button.

 

To add the TimeSpinLists editor to a UX component, select the [Editor-TimeSpinLists] item in the Defined Controls section of the UX toolbox.

 

 

To configure the Time value editor, click the smart field for the Editor configuration genie property in the FormView builder on the Fields tab.

The configuration genie allows you to specify if the 'Now' button should be shown.

 

 

 

 

UX Component - FormView Control - Pre-defined Editors - Date/Time Value Editor - A new pre-defined editor for editing date/time values in a FormView control has been added.

The editor, as shown below, displays SpinList controls for the month, day, year, hour, minutes and AM/PM values.

The editor also displays a button to set the selection in the SpinList controls to the current date and time.

You can configure the editor to hide the 'Now' button and to show a 'Clear' button which 'un-sets' the date/time value.

 

To add the DateTimeSpinLists editor to a UX component, select the [Editor-DateTimeSpinLists] item in the Defined Controls section of the UX toolbox.

 

 

To configure the Time value editor, click the smart field for the Editor configuration genie property in the FormView builder on the Fields tab.

The configuration genie allows you to specify if the 'Now' button should be shown.

 

UX Component - FormView Control - Pre-defined Editors - Numeric Keypad Editor - A new pre-defined editor for editing numeric values in a FormView control has been added.

The editor, as shown below, displays a keypad that allows the user to enter numbers. When editing a value using the numeric keypad, the native keyboard on a mobile device is not used.

A configuration genie allows you to specify various settings for the keypad.

 

 

To add the Numeric KeyPad editor to a UX component, select the [Editor-NumericKeypad] item in the Defined Controls section of the UX toolbox.

 

 

 

 

To configure the Numeric KeyPad  editor, click the smart field for the Editor configuration genie property in the FormView builder on the Fields tab.

 

 

The configuration genie (shown below) allows you to configure various settings for the keypad.

 

The Custom formatting Javascript allows you to define code that formats the number when it is displayed in the Keypad number display area.

For example, in the image below, the number is formatted to display a $ sign and two decimal places.

 

 

To achieve this, the Custom formatting Javascript property was defined as:

 

return Number(val).toFormat('$#,##0.00;$ (#,##0.00);------');

 

UX Component - ControlBar Control - Disclosures - Injectible Content - When you create a Disclosure in a ControlBar you can now set the Disclosure type to Injectible Container.

Previously, you could add a special Injectible Content placeholder in the HTML that you defined for the Disclosure. Setting the Disclosure type to Injectible Container is easier than using Injectible Content placeholders in the HTML and it has another advantage -- it makes it very easy to display List controls in the disclosures displayed by the Control Bar.

 

Watch Video - Part 1
Watch Video - Part 2

Download Component

 

 

CSS - Shared Styles - You can now define CSS styles that are shared across all stylesheets. Shared styles can be defined at the system level or at the project level.

The shared styles are stored in the following locations:

The shared styles are defined in a file called style.sass in the _sharedStyles folder. The shared styles can include SASS definitions.

For example, if you define a CSS selector called .style1 in the [Project Folder]\css\_sharedStyles\style.sass file, this selector will be available in all components, regardless of what stylesheet the component uses.

 

 

UX Components - ControlBar Control - Disclosure Buttons - Margins -  You can now specify margins for the content that is displayed in a ControlBar disclosure.

 

 

For example, in the image below, the List in Window disclosure button in the ControlBar in the UX footer displays a disclosure and sets the top, bottom, left and right margins to constrain the size of the disclosure content, giving the impression that the List is displayed in a window.

 

 

 

AlphaLaunch - AEX Files -  When you register a UX component as an AlphaLaunch App you can now specify that .aex files for this App should be compiled and published.

 

Xdialog -WaitDialog - You can now set the width of the Xdialog Waitdialog.

 

 

 

Example:

 

dim p3 as waitdialog
p3.create(3,"bounce",500) 'set with width to 500
p3.set_color("dark green")
p3.Set_Bottom_Message("This is the bottom row message - line1." + crlf() + "Line2")
p3.Set_Message("This is the top row message.")

 

'to close the waitdialog

p3.close()

 

 

 

UX Component - List Control - Allow Any Value - The List control now has a new property, Allow any value, that allows you to set the List value to a value not in the List data. If this property is not checked (the default), you cannot set the List value to a value that is not in the List data.

 

UX Component - Defined Control - Time Editor for FormView Control - A new pre-defined editor for a time value in a FormView control is available.

To select the time value editor, select [Editor-TimeSpinLists] from the list of controls in the Defined Controls section.

 

 

The image below shows a form control on the left with a time value and a time value editor on the right. The time value editor is implemented using three spin lists - one for hours, one for minutes and one for AM/PM.

You can modify the values in the hours spin list if you want to user to select minutes in multiples of 5, 10, 15 minutes, etc.

 

 

AlphaLaunch - Download Applications from S3 - By default, when you publish an App to AlphaLaunch, the AlphaLaunch client (i.e. the App running on the mobile device) will download the App from the same folder to which the App was published. The App will be published to a folder in the webroot of the standard Alpha Anywhere server, the Alpha Anywhere IIS server, or AlphaCloud.

However, you can also publish the app to a S3 bucket and when the AlphaLaunch user tries to install a new App, the App files will be downloaded from S3, rather than from your Alpha Anywhere server. Of course, once the user actually starts using the App on their device, Ajax callbacks will be handled by your Alpha Anywhere server.

The benefit of downloading Apps from S3 is that you offload work from your Alpha Anywhere server to S3. Also, in certain cases, when using an Android device and downloading an App from an Alpha Anywhere standard server, the install might fail because the App has too many files. By using S3 as the download location, you can circumvent this problem.

 

If you want to publish the App to S3, check the Use Amazon S3 as download site for AlphaLaunch Apps checkbox on the Publish to AlphaLaunch dialog.

 

 

You will need to specify:

 

Xbasic - SQL Server Reporting Services - a5w_report_saveAs() Function - You can now use the a5w_report_saveAs() function to print SSRS reports.

 

Syntax

c filenameOut = a5w_report_saveAs(c reportname, c type, c filter, c order, c filename,P globalVariables , P printOptions, sql::arguments Args)

 

Where

 

Example:

 

dim reportName as c
reportName = "customersbystate.ssrs.a5rpt"


dim args as sql::Arguments
args.add("whatcountry","UK")
 

dim filename as c

filename = a5w_report_saveAs(reportname,"pdf","","","c:\pdf\report1.pdf",null_value(),null_value(),args)
sys_open( filename)

 

 

UX Component - List Control - Detail View - Incremental Refresh After List Populate - A pattern that some mobile App developers use when building offline applications is to automatically do an incremental List refresh when the App is first loaded. This ensures that the user has up to date data on their device. An incremental List refresh (rather than a full refresh) is done so that any unsynchronized edits are not lost. There was no obvious event in which the incremental refresh could be triggered, especially if the List had been configured to download media files to the filesystem.

Therefore, to make this pattern easy to set up, a new property has been added to the List. The Do incremental refresh after List is populated property will allow you to kick off an incremental refresh of the List after the List has been populated.

 

 

UX Component - Action Javascript - File Upload Action - S3 Timeout - When you upload to S3, you can now specify a timeout setting. If you are uploading a large number of files, you might need to increase this setting otherwise, you might get 'permission expired' errors from S3 indicating that the time window in which uploads are permitted has expired.

 

 

 

 

PhoneGap Applications - Usage Descriptions for Plugins -  PhoneGap Build now allows the addition of a <config-file> element into the config.xml file.

http://docs.phonegap.com/phonegap-build/configuring/config-file-element/

This lets you add xml directly to the iOS Info.plist file and Android AndroidManifest.xml file.

This solves an error that you might get when submitting an app to the Apple App Store. The error complains about certain UsageDescription strings not being set in PhoneGap Build Plugins.

E.g.


Camera Plugin : NSCameraUsageDescription

Calendar Plugin : NSCalendarsUsageDescription
 

The entry into the config.xml file to set the UsageDescription strings is:


<config-file platform="ios" parent="NSCalendarsUsageDescription" mode="replace">
    <string>This app will use the Calendar</string>
</config-file>
 


 

 

UX Component - Client-Side Events - onConnectionChange Event - The onConnectionChange event when the device either gets a connection, or looses its connections. The event has a parameter that tells you whether the device has or does not have a connection. Previously, this parameter was not always accurate. Now, it can be relied on.

A common use case for this event is to only show a 'sync' button on a mobile device when a connection is available. In addition, before executing an Ajax callback you might want to first check that the Alpha Anywhere server is responding (it is possible for the Alpha server to be offline even though the device has a connection).

In summary, here are the events and methods that you can use in a Mobile app.

 

Example use of .serverIsAvailable() method

 

var _ok = function() {
    alert('server responded');
};

var _err = function() {
    alert('server did not respond');
};
 

//wait up to 500 milliseconds before calling either the _ok or _err callback function
{dialog.Object}.serverIsAvailable(500,_ok,_err);

 

 

UX Component - List Control - <listObject>.setValue() Method - Several new options have been added to the .setValue() method.

NOTE: These new options only apply if the List is set to allow multi-selection.

 

 

Examples:

//adds values to the current selection
listObj.setValue({select: 'add', value : ['Smith','Jones']});

//remove values from the currently selected value
listObj.setValue({select: 'remove', value: ['Smith','Jones']});

//toggles the selected state of the items in the value array
listObj.setValue({select: 'toggle', value: ['Smith','Jones']});

//select rows in a list programmatically. If function returns true, row is selected.
listObj.setValue({select: 'match', match: function(value,data) {
        //value and data for the current row
        if(data.Country == 'USA') return true;
        else return false;

    }
   }

);

//select rows in a list programmatically. Optionally add to the existing selection
listObj.setValue({select: 'match', additive: true, match: function(value,data) {
    //value and data for the current row
        if(data.Country == 'UK') return true;
        else return false
    }
  }

);
 

UX Component - Alignment Container - Centering Content - The Alignment container allows you to easily center align content. If you have multiple controls in an Alignment container, each control is horizontally centered on its own line.

 

 

However, if you wanted (say) Control 1 and Control 2 to both be on the same line, and center align the combined width of the two controls, you can now wrap Control 1 and Control 2 in a container within the Alignment container.

UX Component - List Control - Lazy Image Loading - A new genie is available to set up a List to use Lazy Image Loading.

A common use case for Lazy Image Loading is when you have a List that displays images that are sourced from a server. If the List has a large number of rows, fetching all of the images from the server will slow down the initial render of the List. However, by implementing Lazy Image Loading, only the images for the rows that are currently scrolled into view will be fetched.

 

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
 
Download Component

You can set a wait time that the List will wait after a row comes into view before the images for the visible rows will be fetched. This prevents fetching images for rows that you scroll past without stopping on. When a row that displays an image that has not yet been fetched is displayed, a 'waiting' image will be displayed. Once the image has been fetched, the 'waiting' image will be replaced with the real image.

To access the Quick Setup Genie, open the List control builder. Click on the Quick access... button at the bottom of the window and then select the List Quick Setup Genie menu item.

 

 

Once the Quick Setup Genie opens, select the Lazy Image Loading option.

 

 

The genie allows you to configure a number of options, such as the name of field in your List data that contains the image URL for the image to display in each row. You can also set the URL of the wait image (the image to display before the real image has been fetched).

When you exit the genie, the genie will automatically set several properties in the List, such as the onListDraw and onScroll event, the List template, etc.

 

AlphaDAO - oData - Authentication Options - You can now specify an Authentication option when building an oData connection string.

 

 

The options are:

 

 

UX Component - List Control - DetailView - addTableRow() Method - The addTableRow() method allows you to programmatically add new rows to a List with a Detail View.

If you are using this method in a loop, then you can add many new rows to a List quite quickly. Under certain circumstances, this might cause a problem.

The circumstances under which this could cause a problem are:

  1. The List is set to persist to storage (so that the application can function offline)
  2. The List storage is set to FileSystem
  3. The App is running in Phonegap.

 

The reason that there is a potential problem under the above scenario is that writing to the FileSystem in PhoneGap is an asynchronous operation. Each time the List is updated, the edits to the List are saved in files written to the FileSystem. But since these write operations are asynchronous, it is possible (actually likely), that the write operation for the next record added to the List will be initiated before the write operation for the current record added to the List has completed, and so on. These overlapping write operations to the FileSystem could corrupt the files used to store the List edits.

The solution to this potential problem is to temporarily suspend persisting the List while the .addTableRow() method is being called in a loop and then once the loop has completed, turn the suspension off and persist the List to storage.

To suspend persisting to the List, you set the List's .suspendPersist property to true.

To turn persisting back on, you set the List's .suspendPersist to false

To manually persist the List after you have turned suspend persist off use the List's .persistToStorage() method. You must pass in an empty object when calling this method.

 

For example:

       


//persist multiple rows in a loop

var listObj = {dialog.object}.getControl('list1');

//suspend list persisting
listObj.suspendPersist = true;

//execute the .addTableRow() method in a loop

//turn list persisting back on
listObj.suspendPersist = false;

//persist the list (passing in an empty object to the .persitToStorage() method.
listObj.persistToStorage({});
 

 

 

UX Component - Panel Navigator - Carousel Mode - If you are swiping to the left or the right to navigate from one Panel Card to another, if the Panel Card you are navigating from allows for vertical scrolling, you could easily start scrolling the Panel Card vertically while you were also swiping left or right. This creates an undesirable visual effect. Now, once you start moving the Panel Card to the left or right (to transition from one Panel Card to another), vertical scrolling the Panel Card is disabled.
 

AlphaDAO - SQLite - AlphaDAO now has built-in support for SQLite. Previously, you could connect to a SQLite database by installing an ODBC driver. However, since there was no syntax handler for SQLite, there was no support for Portable SQL or the Portable SQL functions that AlphaDAO exposes. As a result, certain operations would fail.

Now, with built-in support for SQLite, there is no longer any need to install an ODBC driver and all Portable SQL functions (with the exception of Geography functions, which SQLite does not support) are supported.

Full details on SQLite support are in the documentation.

 

UX Components - Checkbox and Radiobutton Controls - Render as ButtonList - Icon Alignment - A new property has been added to the builder allowing you to better control the placement of the icon relative to the text.

The Button style property has these options:

 

 

Bugs

Application Server - Stripe - The Stripe methods (built into Alpha Anywhere using Action Javascript) did not work when using the Application Server. This was because the Stripe methods use a Node.js module and the Node modules were not getting installed when the Application Server was installed.

UX Components - List Control - Detail View - Persist to FileSystem - Various improvements have been made to the way the List control persists offline data to the file system.

Application Server - Alternate Login - Facebook - As a result of a change Facebook made to the data returned on a successful login, the Facebook Alternate Login was throwing an error. This is now fixed.

 

UX Component - Apply Security Client-side - If you checked the option to apply security client-side, but did not also check the option to pre-render the component at design-time, the security settings were not applied on the client-side.

 

UX Component - Image Controls - Touch Events - Mobile Devices - 300ms Delay - If you defined a touch event for an image control, on a mobile device, the browser would add a 300ms delay before firing the event. This is now fixed.

 

UX Component - List Control With Detail View - CRUD Operations - Regional Settings - If the regional settings on the server specified a comma as the decimal characters, and the UX was configured to show decimals with a period and to require decimal numbers to be entered with a period, update and insert operations would fail.

SSRS Reports - Internal Parameters - When defining a SSRS report you can specify that certain parameters are 'internal' Previously, when printing a report that has internal parameters, the UI would prompt for values for internal parameters. Internal parameters should not have been exposed in the user interface.

AlphaLaunch - Embedded UX Components - The URL for Ajax Callbacks was not getting set correctly for child UX components loaded by the master UX component if the child UX components were set be 'precomputed' (rather than loaded by making an Ajax Callback0.

UX Component - Absolute Container - Bulk Operations - Recalculate UX Components - If you performed a bulk recalculate of UX components, the settings in an Absolute Container were lost.

UX Component - List Control - Detail View - Persist List Data to Storage - FileSystem - Incremental Refresh - In build 4.4.4, the ability to persist the List data to the filesystem, rather than localStorage, was introduced. This provided for a large increase in the amount of data that could be used in offline mobile apps.  A bug was fixed when doing an incremental refresh on the List when the List data was being persisted to the filesystem.

UX Component - List Control - Order - Multi-level sort definitions did not work correctly.

UX Component - List Control - Detail View - Client-side Grouping - New Records - If a List had client-side group breaks, then after a new record was added and the List was synced, focus did not remain on the new record.

Reports - Report Server - Storage Connection Strings - If a report had a reference to an Amazon S3 image that used JSON syntax for the image name, the storage connection string could not be resolved if the report was printed using the Report Server.

Tips

Sample Mobile Application - Export to Excel - This sample application shows how you can create a mobile application that has a button that makes an Ajax callback to the server. The Xbasic function that handles the callback creates an Excel file and then the mobile device downloads the excel file and opens it using the native Excel viewer on the device.

Download example

 

 

UX Component - PhoneGap - iOS Keyboard - Next / Previous Keyboard Buttons - When you run a UX component on a native iOS device, the native iOS keyboard has next/prev buttons to navigate to the next and previous input control on the screen. If you have a UX component with multiple panels and focus is on the last input control on the currently visible Panel, if you tap the next button, focus will go to the next input control, which may be a Panel Card that is not currently visible. Clearly, this is undesirable.

The solution is to disable input controls that are not currently on a visible PanelCard.

Assume you have a PanelNavigator (called 'PANELNAVIGATOR_1') with child PanelCards.

 

You could add the following expression the the client-side enable expression for each of the input controls.

 

enableControl('PANELCARD_1')

 

where 'PANELCARD_1' was the name of the Panel Card in which the input control had been placed.

 

The enableControl() function would be defined as follows:

 

function enableControl(txt) {
var p = {dialog.object}.panelGet('PANELNAVIGATOR_1');
var ps = p.state;
if( p.state.activePanel == txt) return true;
return false;
}

 

This function will return true if the active PanelCard name matches the passed in PanelCard name.

 

So, only input controls on the currently active PanelCard will be enabled and the iOS keyboard next/previous buttons will only cycle through the controls on the current PanelCard.

 

 

 

Alpha Anywhere V4.4.4 - Build 4346-4889 18-May-2017

NOTICE:  Alpha Anywhere is now being being built with Visual Studio 2015. Previously Alpha Anywhere was built using Visual Studio 2013.

 

IMPORTANT: If you have UX components with Lists that have updateable Detail Views and these UX components were defined as pre-rendered then you will need to edit these components and resave them so that the pre-rendered code can be re-generated. You can use the Edit, Bulk Operations, Recalculate UX Components menu item to do a bulk update of your UX components.

 

Videos

AlphaLaunch Publishing Apps to a Device using AlphaLaunch Publishing Apps to an App store (especially the Apple App store) can be a time consuming and frustrating experience. Using AlphaLaunch you can quickly and easily publish Apps to Apple and Android devices, completely bypassing the App stores.

In this video we show how you can publish an App to a device using AlphaLaunch

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4

Date added: 2017-03-26
UX Component Mobile Applications with Persistent Logins A common pattern in mobile applications is to not require the user to login to the application after they have successfully logged in for the first time.  The login should be persistent until is is explicitly revoked by the action of an Administrator, or until the end of the persistent login period is reached.

Unlike a traditional Web application built using the Alpha Security Framework, the user will not have to log in again once their session expires, or when they restart the application.

In this video we show how this pattern is achieved.

(Requires build 4307 or above.)

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4
Watch Video - Part 5
Watch Video - Part 6

Download Component

Date added: 2017-04-29
UX Component - ViewBox Control Get Data for Current Row in ViewBox A common use case for a ViewBox is a light weight alternative to the List control. In a List control it is easy to get the data for the row that the user clicked on. 

In this video we show how a ViewBox that is configured to display a list of data can be configured so that the data for the row that was clicked on can be obtained.


Watch Video

Download Component

Date added: 2017-05-14

 

 

IMPORTANT: If you have UX components with Lists that have updateable Detail Views and these UX components were defined as pre-rendered then you will need to edit these components and resave them so that the pre-rendered code can be re-generated. You can use the Edit, Bulk Operations, Recalculate UX Components menu item to do a bulk update of your UX components.

If you have PhoneGap applications that use Lists with updateable Detail Views, and if you want to update the server that handles the Ajax callbacks from your PhoneGap applications, you will need to rebuild your PhoneGap applications.

Features

Xbasic - JSON - Reshape JSON - extension::JSON::FormatMapped() Method - It is sometimes necessary to 'reshape' a JSON document, changing property names, creating arrays and objects from properties, etc.

The extension::JSON::FormatMapped() method allows you to do this.

The method takes two arguments:

 

For example, consider the following input JSON file:

dim jsonIn as c
jsonIn = <<%str%
{
    "id" : "001",
    "fname" : "John" ,
    "lname" : "Doe",
    "address1" : "12 Main Street",
    "address2" : "Box 20"
}
%str%

 

Say you want to reshape this JSON document so that it looks like this:

{
    "person": {
        "id": "001",
        "firstname": "john",
        "lastname": "public",
        "address": [
            "12 Main Street",
            "box 20"
        ]
    }
}

Here is the Map that would define to achieve the above transformation:

 

 

dim jsonMap as c = <<%str%
{
    "person" : {
        "id" : "id" ,
        "firstname" : "fname" ,
        "lastname" : "lname" ,
        "address" : [ "address1" , "address2" ]
    }
}
%str%

 

Notice that in the input JSON, there is a flat list of properties. The firstname and lastname properties are called "fname" and "lname"

 

In the output document, the firstname and lastname properties are called "firstname" and "lastname", the two address fields are in an array called "address" and all of the properties are now a child of a new object called "person"

 

Here is how you would transform the input JSON (jsonIn) using the map (jsonMap)

 

dim jsonOut as c

jsonOut = extension::Json::FormatMapped(jsonmap,jsonin)

jsonOut2 = json_reformat(jsonOut) 'format the JSON

 

 

 

 

Xbasic - JSON - Flatten JSON - extension::JSON::ExtractMapped() Method - Creates a flattened JSON object from a complex JSON object. The flattened JSON object has all properties at the top level, with no nested objects are arrays.

 

The extension::JSON::ExtractMapped() method allows you to do this.

 

Assume you have a complex JSON document as shown below. Note that the only top-level property is "person"


dim jsonIn as c
jsonIn = <<%json%
{
    "person": {
        "id": "001",
        "firstname": "John",
        "lastname": "Dublic",
        "address": [
            "12 Main Street",
            "Box 20"
        ],
        "otherInfo" : {

            "x": "value of x",

            "y" : "value of y"

        }
    }
}
%json%
 

 

Say you want to flatten this JSON document so that all properties are at the top level and also change some of the property names. The resulting JSON document should look like this:

 

 

{
    "id": "001",
    "fname": "john",
    "lname": "public",
    "address1": "12 Main Street",
    "address2": "box 20",
    "x_value": "value of x",
    "this is the y value": "value of y"
}

 

 

Here is the Map that would define to achieve the above transformation:


dim jsonMap as c
jsonMap = <<%json%
{
    "person" : {
        "id" : "id" ,
        "firstname" : "fname" ,
        "lastname" : "lname" ,
        "address" : [ "address1" , "address2" ],
        "otherInfo" : {

            "x" : "x_value",

            "y" : "this is the y value"

        }
    }
}
%json%

 

 

Here is how you would transform the input JSON (jsonIn) using the map (jsonMap)

 


dim jsonout as c
jsonOut = extension::Json::ExtractMapped(jsonMap,jsonIn)
dim jsonout2 as c
jsonout2 = json_reformat(jsonout) 'format the JSON

 

 

UX Component - Style 'Tweaks' - When working with version 3 and above styles (these include iOS7, AndroidLight, AndroidDark, Alpha), you can now define style 'teaks'. Tweaks are adjustments to the style definition that are stored in a separate file in the Web Project folder. The adjustments include new sub-themes and CSS classes, and changes to existing sub-themes and CSS classes.

Normally when you edit a system style (such as 'Alpha'), a local copy of the style is saved in the Web Project folder and your edits are applied to the local copy of the style.js and style.sass files. The disadvantage of this approach is that if, in a future version of Alpha Anywhere, the style is changed (to fix a bug or to add support for a new control type), the changes made to the system version of style.js and style.sass will not be reflected in the local copy of these files that you created when you edited the style. You would need to manually edit the system copy of these files and copy changes to the local copy of these files. This would be complicated because it would not be easy to find the parts of the file that had changed.

On the other hand, since style tweaks are stored in a separate file, there are no local copies of the style files you are tweaking. Therefore if a future version of Alpha Anywhere updates the style, the tweaks are applied to this updated version of the style and your tweaked style will automatically have all of the changes made to the system style.

Style tweaks for a particular style are stored in this file:

<web project folder>\css\StyleTweaks\<style name>\styleTweaks.json

 

 

To define style tweaks, click the smart button for the Style sub-theme and CSS 'tweaks' property.

 

 

NOTE: If you customize the style colors and fonts using the smart field for the Customize style color and fonts property, the changes to the SASS variables that define the style's colors and fonts are also stored in the style's Tweaks file.

 

NOTE: You can also adjust the CSS and sub-themes in a style using these properties:

However, the adjustments made here apply ONLY to the component you are editing, whereas style 'tweaks' apply to all components in the Project that use the tweaked style.

 

UX Component - FormView Control - Pre-Defined Editors - TextArea - A new pre-defined editor for a FormView control is now available in the Defined Controls section of the UX toolbox. The [Editor-TextArea] pre-defined control creates an editor for a FormView value. The editor uses a TextArea control and it has a vertical scroller so that long text can easily be scrolled on touch devices.

 

Javascript Editor - Auto-complete for built-in Node modules - When you are editing Node Javascript code in a Javascript editor in Alpha Anywhere, you now get auto-complete for built-in Node modules. For example, assume that you enter this code into your Javascript code to get the Node filesystem module:

var fs  = require('fs')

 

Now, when you type

fs.

you will get auto-complete, as shown in the image below:

 

 

Node API s - The Web Control Panel now has a new category - Node APIs.

 

 

A Node API is similar to a Node Service in that they both allow you to call code written in Node from Xbasic. The difference is in how you call the code.

A Node service exposes a single piece of functionality to Xbasic. You can invoke the Node service using the node_request_result() function.

For example, assume you have a Node service called mergeData. You would call this service, passing in arguments to the service, as follows:

dim p as p

p.name = "Fred"

p.city = "Boston"

dim result as c

result = node_request_result("mergeData",p)

 

On the other hand, a Node API allows you to define an Xbasic class with multiple methods whose method are implemented using Node. Your Xbasic code invokes the Node code by calling methods on an Xbasic class instance. Your Xbasic code will create an instance of the class by declaring a variable of type ::NodeServices::name_of_your_Node_API and then calling methods of this class.

For example, assume you have created a Node API called myAPI and that this API exposes two methods, method1() and method2() and that each method takes a single character argument. Here is how you would invoke these methods from your Xbasic code:

 

'Dim an instance of the API class

dim x as ::NodeServices::myAPI

 

'now call methods of the class

dim result1 as c = x.method1("alpha")

dim result2 as c = x.method2("beta")

 

In effect, the Node API allows you to extend Xbasic with methods that are implemented using Node.

 

NOTE: Future versions of Alpha Anywhere will allow for another use of Node APIs. You will be able to expose REST APIs whose endpoints are implemented using a defined Node API.

 

How to Create a Node API

To create a new Node API, select the Node APIs category in the Web Control Panel and then click the New button.

This will open a dialog where you can name the Node API and define the methods and implementation for the API

The API methods are defined in the Definition pane (shown in the image below). The syntax used for defining the Node API methods is the same syntax used for defining an Xbasic class. Note that the Definition does not include any actual Xbasic code for implementing each method. It simply define the functions that the API will implement.

The actual implementation of the methods is coded in Node code on the Implementation pane.

 

 

The Implementation pane fills in the stub Node code to implement the API methods. You will fill in the actual code for each of the functions in the API.

 

 

When you click the Save button two files are created in the node_services folder in your Web Project

When you edit a previously create Node API, the .js file is opened in the Alpha Anywhere Javascript editor, but the editor toolbar shows a special button (API Definition...) at the right edge of the toolbar:

 

 

The API Definition... button will bring up the Create Node API dialog (shown in the above images) where you can edit the API definition. When you exit the dialog, the the Implementation file (i.e. the .js file you are editing) will be updated to reflect the edited API definition.

 

Example

In this example, we will show how to create a Node API with four methods:

 

Here is how this API is defined in the Definition pane of the Create Node API dialog:

 

 

The code is reproduced below:

 

define class fileoperations
    function readfile as c(filename as c)
        helptext "read file"
    end function
    function writefile as l(filename as c ,contents as c)
        helptext "write a file"
    end function
    function fileInfo as fileInfo(filename as c)
        helptext "return information about a file"
    end function
    function specialN as n(n1 as n ,n2 as n)
        helptext "does some math"
    end function
end class

define class fileInfo
    dim filename as c
    dim filesize as n
    dim fileTime as c
end class

 

 

Notice that the fileInfo method's return type is fileInfo. fileInfo is defined as a class that has these properties: filename, filesize and fileTime.

When you create Xbasic functions that return multiple values, it is common to define the return type of the function as P ( as pointer). In the case of a Node API definition, you cannot define a method whose return type is P. If you want to define a method that returns multiple values, you must define a class, as shown above, and set the function return type to the class.

The definition shown above simply defines what the methods of the Node API are and what input parameters each method takes. The Definition does not contain any Xbasic code to implement the functionality of each method.

The implementation for the above definition is shown below:

Note that the implementation is written using Node code.

 

exports.api = {
    //read file
    // inputs:
        // call.arguments.filename - string
    // returns: string
    readfile : function(call) {
        var fs = require('fs');
        var _cb = function(err,data) {
            if(err) {
                call.error(err);
            } else {
                call.return(data)
            }
        }
        fs.readFile(call.arguments.filename,'utf8',_cb);
    },
 

   

    //write a file
    // inputs:
        // call.arguments.filename - string
        // call.arguments.contents - string
    // returns: bool
    writefile : function(call) {
        var fs = require('fs');
        var _cb = function(err) {
            if(err) {
                call.return(false)
            } else {
                call.return(true)
            }
        }
        fs.writeFile(call.arguments.filename, call.arguments.contents,_cb);
    },

 

   
    //return information about a file
    // inputs:
        // call.arguments.filename - string
    // returns: fileInfo { filename : "" , filesize : 1 , fileTime : "" }
    fileInfo : function(call) {
            var fs = require('fs');
            var _cb = function(err,stats) {
            if(err) {
                call.error('file not found');
            } else {
                var _d = {filesize: stats['size'], 'fileTime' : stats['mtime'], filename: call.arguments.filename}
                call.return( _d );
            }
    }
    fs.stat(call.arguments.filename,_cb);
},
 

    //does some math
    // inputs:
        // call.arguments.n1 - number
        // call.arguments.n2 - number
    // returns: number
        specialN : function(call) {
            var n = call.arguments.n1 + call.arguments.n2
            call.return(n);
        }
};

 

The implementation is a Javascript file that exports an object with the same name as the Node API. This object has function for each of the methods in the API definition.

The prototype for the object is automatically created from the Node API definition.

Notice that the implementation of the fileInfo method returns an object with properties that match the definition of the properties of the fileInfo class in the Node API definition.

Each method defined in the Implementation takes as its input an argument called call. This argument is an object that has a property called arguments which contains the input parameters to the method and it also has two methods, return() and error(), that allow you to return a result from the function, or report an error.

 

To use this API from your Xbasic code:

 

'Dim an instance of the API class

dim fo as ::NodeServices::fileoperations

 

 

dim p as p
p = fo.fileInfo("c:\myfiles\file1.txt")
?p.filename
= "c:\myfiles\file1.txt"
?p.filesize
= 2942097
?p.fileTime
= "2017-05-10T14:26:04.193Z"

 

 

 

 

Xbasic - pdf_fillinFields_get() - Gets a list of the fill-in fields in a PDF file. If a PDF file is created with fill-infields, this function will extract the names of all of the fill-in fields in the file. You can optionally extract additional information about each field.

Syntax

c result = pdf_fillinFields_get(c pdfFilename [, L flagExtendedInfo])

 

 

IMPORTANT: This function wraps a 3rd party library which you must install yourself before you can use this function. The download link for this library is: https://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/pdftk_server-2.02-win-setup.exe

 

Examples (from Interactive window):

dim fn as c

fn = "c:\mypdffiles\pdfform1.pdf

?pdf_fillinFields_get(fn)

 

= {
    "first_name": "",
    "last_name": "",
    "date": "",
    "football": "",
    "baseball": "",
    "basketball": ""
}

 

 

Get extended information (from Interactive window):

 

dim fn as c

fn = "c:\mypdffiles\pdfform1.pdf

?pdf_fillinFields_get(fn,.t.)

= [
    {"title": "first_name","fieldType": "Text","fieldFlags": "0","fieldValue": ""},
    {"title": "last_name","fieldType": "Text","fieldFlags": "0","fieldValue": ""},
    {"title": "date","fieldType": "Text","fieldFlags": "0","fieldValue": ""},
    {"title": "football","fieldType": "Button","fieldFlags": "0","fieldValue": ""},
    {"title": "baseball","fieldType": "Button","fieldFlags": "0","fieldValue": ""},
    {"title": "basketball","fieldType": "Button","fieldFlags": "0","fieldValue": ""}
]

 

 

Xbasic - pdf_fillinFields_merge() - Merges data into a PDF file that has fill-in fields, creating a new PDF file with the filled in data. You can use the pdf_fillinFields_get() function to get the name of the fill-in fields in the PDF file.

Syntax

L result = pdf_fillinFields_merge(c pdfFileIn, c pdfFileOut, c JSONData)

 

 

IMPORTANT: This function wraps a 3rd party library which you must install yourself before you can use this function. The download link for this library is: https://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/pdftk_server-2.02-win-setup.exe

 

The field values that you use in the JSON data must match the defined 'Export value' in the PDF form. Win the PDF form designer, you can specify an 'export value' for each field. In the Example shown below, the 'Export value' for the 'football', 'baseball' and 'basketball' fields was defined as 'Yes'.

 

Example:

 

dim jsonData as c
jsonData = <<%str%
{
    "first_name": "Fred",
    "last_name": "Smith",
    "date": "12/18/2003",
    "football": "Yes",
    "baseball": "Yes",
    "basketball": "Off"

}
%str%
 

dim pdfIn as c

dim pdfOut as c

pdfIn = "c:\mypdffiles\pdfform1.pdf

pdfOut = "c:\mypdffiles\pdfform1_filled.pdf


pdf_fillinFields_merge(pdfIn,pdfOut,jsonData)

 

Xbasic - Functions - Arguments as Arrays - You can now specify that an input argument is an array by adding a suffix of [] to the argument name. Previously you had to set the input type of the argument to P if the argument was an array.

NOTE: The array is passed to the function by reference.

 

Example:

 

function asText as c(arr as c[])
    asText = crlf_to_comma( arr.dump() )
end function

 

Testing:

dim arr[2] as c

arr[1] = "alpha"

arr[2] = "beta"

?asText(arr)
= "alpha,beta"
 

 

 

Xbasic - Functions - Return Arrays - Previously, an Xbasic function could return an array by setting the return type of the function to a Pointer. Now you can explicitly set the return type to an array by adding a suffix of [] to the return type.

 

function asAnArray as c[] (commaList as c)
    commaList = comma_to_crlf(commaList)
    asAnArray.resize(line_count(commaList))
    asAnArray.initialize(commaList)
end function

 

 

Testing:

 

arr = asAnArray("one,two,three")
?arr.size()
= 3

?arr.dump()

= one
two
three

 

Xbasic - Functions - Return a typed Array - You can now define Xbasic functions that return arrays of an explicit type by adding a suffix of [] to the return type. Previously you could only return a generic Pointer value.

 

For example, assume you had defined the following class:

 

define class mynamespace::point
dim x as n
dim y as n
end class
 

You can now define a function that returns an array of the mynamespace::point type.

 

function ToPointArray as mynamespace::point[](points as c)
    points = strtran(points,";",crlf())
    ToPointArray.initialize_properties("x,y",points)
end function

 

Testing:

pa = ToPointArray("1,1;2,2;1,2")

? pa[1]
= x = 1
y = 1

 

 

Web Control Panel - UX Components - Pre-rendered Components - Warning Dialog -  If you update to a newer version of Alpha Anywhere and you open a web project that contains any UX components that have been set to pre-render and any of these components were last pre-rendered with an older version of Alpha Aynwhere, you will now get a warning telling you that these UX components need to be re-rendered. The warning dialog will allow you to click a 'Bulk Update' button to automatically update all of the UX components that need updating.

 

UX Component - List Controls - Offline Applications - PhoneGap - Using the File System to Persist List data - When you build a mobile app that is intended to operate offline, the typical pattern is to use List controls with Detail Views and to turn on the option to persist the List data to storage.

The data in the List are persisted to the browser's localStorage, which is limited to about 5mb of data.

Now, if your mobile application is run as a PhoneGap application, you can persist the List data to files in the device's file system. This will allow you to work with much more data while you are offline.

To turn on the feature to persist List data to the file system, set the Persist where property to FileSystem.

 

 

When you set the Persist where option to FileSystem, the Persist mode option is automatically set to Edits and the property is hidden.

If you set Persist where to LocalStorage, you can set the Persist mode to either 'Full', or 'Edits'.

In 'Full' mode, each time the data in the List are edited, the entire List is persisted to localStorage (this is the mode that is implicitly used in all versions of Alpha Anywhere prior to this version).

In 'Edits' mode, each time the data in the List are edited, only the edited rows are persisted to storage.

 

NOTE: f you select the FileSystem option and your component is not running in PhoneGap, Alpha Anywhere will automatically set the option back to LocalStorage.


How Persisting Data to the FileSystem Works

When you persist List data to localStorage, when the List is initially populated the List data is persisted to localStorage. Each time the List data are edited, the entire List is persisted again to localStorage (unless you change the Persist mode option to Edits).  Because writing to localStorage is so fast, and because there is a built-in limit (of approximately 5mb) to the amount of data that must be written to localStorage on each edit, there is no perceptible delay when you are editing the data in the List.

However, writing to the FileSystem is much slower than writing to localStorage and because there is no longer a built-in limit as to the amount of data in the List, a different approach is taken when the FileSystem option is used. When the List is initially populated, all of the data in the List are written to a file in the FileSystem. Each time the List is edited, the only the rows in the List that have been edited are written to a second file in the  FileSystem. This will file will typically be substantially smaller than the first file (that contains all of the List data), and since the file is likely very small, writing this file to the FileSystem will be very fast, and again, there will be no perceptible delay when you are editing data in the List.

When the List is synchronized data in the synced rows are written to a third file in the FileSystem and the primary keys of any deleted rows are written to a fourth file in the FileSystem.

The filenames of these four files in the FileSystem are:

 

Where:

<listName> - is the Id of the List.

<namespace> is the value of the Namespace property (see image below).

NOTE: If the List data are being persisted to localStorage, the Namespace property is used in constructing the localStorage key name. If the List data are being persisted to the FileSystem , the Namespace property is used in constructing the filenames for the four files used to persist the List data and edits.

 

Location of the List Data Files in the FileSystem

The files for the List data are stored in the device's 'saved' filesystem. The location of the device's 'saved' filesystem is returned by the {dialog.object}.phoneGapGetLocalDirURL('saved') method. The files are stored in a directory (called _offline by default) in this location.

The following methods can be use to get the file system URL and folder for the List data files:

{dialog.object}._persistFS() - the file system URL of the directory in which the List data sub-directory is located

{dialog.object}._persistFolder() - the sub-folder in which the files are actually stored - name has a trailing / character.

The actual folder name of the files is therefore:

{dialog.object}._persistFS() + {dialog.object}._persistFolder()

 

For example, the fully qualified name of the file that contains all of the data in the List when the list is initially populated is therefore (assuming the List id is LIST1 and the UX Local Storage Namespace property was set to NS1):

{dialog.object}._persistFS() + {dialog.object}._persistFolder() + 'NS1.LIST.LIST1'

 

NOTE: In the case where the component is running in AlphaLaunch, the base folder for the files is in a special folder returned by the  A5.shell.getAppFileStorageDir() method. The {dialog.object}._persistFS() will return the appropriate base folder name when the component is running in AlphaLaunch.

 

List Virtualization

If you are populating a List with a large amount of data, it is strongly recommended that you turn on the List's virtualization feature. With virtualization turned on, populating a List with a large amount of data is substantially faster than populating the List with virtualization turned off.

To turn on List virtualization, set the Virtualization type property to Dynamic as shown in the image below.

 

 

 

 

DetailView Button Genie

The DetailView Button Genie now has two new options as shown in the image below:

 

 

 

Delete List Storage - This deletes the files used to store the List data. (If the List is set to persist to Local Storage and the Persist mode is set to Edits, this option will delete the List data from localStorage)

Dump storage data - Dumps out the contents of the files that contain the List data (If the List is set to persist to Local Storage and the Persist mode is set to Edits, this option will dump the List data stored in localStorage). The data can be dumped to a file on the server, a bucket on Amazon S3, and can also be written to a DIV or placeholder on the screen.

 

NOTE The DetailView Button Genie is accessed by clicking the [List-Detail View-Buttons] item in the UX toolbox  Defined Controls section

.

 

 

Deleting Storage

You can delete the files that contain the List data using this Javascript:

var ls = {dialog.object}._localStorageSettings;
{dialog.object}._persistToLocalStorageInitializeKeys(ls,'listId',true);

 

Deleting the files that contain the List data can be useful when debugging an application.

 

 

Grid Components - Publish Meta Data Files - Published grid components do not include meta data that is needed to open the component in the Grid Builder. Therefore the published grid files found in the server webroot can not be edited in the Grid component Builder. A new option has been added to the publish profiles to 'Publish Grid Meta Data Files'. This option is selected by default and a special data file with the component name and a '_a5wcmp_metadata' file extension will be published when the grid is published.

NOTE: The motivation behind publishing meta data files is so that if a developer no longer has access to the original grid component files (.a5wcmp files) from the Web Project Folder, but does have access to the published .a5wcmp files, they will still be able to edit the Grid component files in the Grid builder (as long as they also have access to the published meta data files - _a5wcmp_metadata). The published files for all other component types (i.e. other than Grids) can be edited in the development program component builders (and therefore it is not necessary to publish meta data files for these component types).


The special _a5wcmp_metadata file is not used by the web server, but can be converted into the original editable grid using an option 'Create Grid Component From Meta Data File' found in the Web Control Panel 'More...' drop down.

This option should only be turned off if there are backup copies of the original grids available outside of the development system.

UX Component - Mobile Applications - Persistent Logins - A common pattern in mobile applications is to not require the user to login to the application after they have successfully logged in for the first time.  The login should be persistent until is is explicitly revoked by the action of an Administrator, or until the end of the persistent login period is reached.

NOTE: The canAjaxCallback server-side event previously would only emit user-defined Javascript if the event denied permission for the callback. Now, user defined Javascript can be emitted even if the Ajax callback is allowed. This change was made to support the Mobile Application with Persistent Login pattern.



For more information on the approach used to implement this pattern, please view this document.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4
Watch Video - Part 5
Watch Video - Part 6

Download Component
 

When you create a new UX component a new template is available for the persistent login pattern.

 

 

Alpha Anywhere Application Server - Self-signed Certificates - A change has been made in the way self-signed certificates are generated.

Alpha Anywhere Application Server - Request Object - As part of an ongoing initiative to standardize functionality between the Alpha Anywhere Application Server (AA Server)  and the Application Server for IIS (AA Server for IIS), the Request object in the AA Server server will be undergoing a number of changes. While no immediate action is required from developers, there are a number of planned changes that will potentially introduce incompatibilities for existing Xbasic code. Alpha Software is committed to minimizing the impact of these changes, and this release of Alpha Anywhere includes several new properties and methods on the Request object to allow developers to begin transitioning their code at their convenience. Future releases will continue to add functionality to ease this transition. All new functionality will work identically when running under either the AA Server or the AA Server for IIS.

The goal of these changes is to ensure that your applications will work identically on both the AA Server and the AA Server for IIS, thus allowing for a seamless transition between servers should you decide to deploy your app using the AA Server for IIS

New Functionality
 

Request.Cookies will be changing to be a System::Web::HttpCookieCollection in the future. Currently it is an Xbasic property class ("dot variable"). Once changed, any Xbasic code expecting a property class will fail. To prepare for the upcoming change, the new HasCookie() and GetCookie() methods can be used to replace code that directly operates on Request.Cookies. These methods will continue to work even after the underlying type of Request.Cookies is changed. These methods also work consistently in both the AA Server and the AA Server for IIS.

Request.GetCookie() returns null if the specified cookie does not exist, or returns a System::Web::HttpCookie instance if the cookie exists. Existence of the cookie can be checked in advance with Request.HasCookie().

Sample to see if a cookie exists:

if Request.HasCookie("MyCookie") then
    'cookie exists in the request
else
    'cookie is NOT included in the request
end if



Sample to read a cookie's value:

dim GreetingName as c = ""
if Request.HasCookie("Greeting") then
    dim GreetingCookie as System::Web::HttpCookie = Request.GetCookie("Greeting")
    GreetingName = GreetingCookie.Value
else
    GreetingName = "new user"
end if
Response.Write("Welcome " + GreetingName)
 


Sample of updating legacy code:
Sample old syntax:

dim MyCookieValue as c = ""
if eval_valid("Request.Cookies.MyCookie")
    MyCookieValue = Request.Cookies.MyCookie
end if
 

Sample new syntax:

dim MyCookieValue as c = ""
if Request.HasCookie("MyCookie")
    MyCookieValue = Request.GetCookie("MyCookie").Value
end if


 

Headers will be changing to a System::Collections::Specialized::NameValueCollection. Currently it is a character string containing the raw header text of the HTTP request. To prepare for the upcoming change, the new GetHeader() method can be used to replace code that directly operates on Request.Headers. These method will continue to work even after the underlying type of Request.Headers is changed. This method also works consistently in both the AA Server and the AA Server for IIS.

The Request.GetHeader() method always returns a string value. If the specified header name does not exist in the request, the returned value will be an empty string. There is no distinction between a header that does not exist, and a header that exists with an empty value.

Sample old syntax to get the value of a specific header:

dim HeaderValue as c = ""
HeaderValue = alltrim(extract_string(wr.Headers,"MyHeader: ",chr(10)))
 


Sample new syntax to get the value of a specific header:

dim HeaderValue as c = Request.GetHeader("MyHeader")



Deprecated Properties


Additional Documentation

Full documentation for the .Net class System::Web::HttpCookie can be found at https://msdn.microsoft.com/en-us/library/system.web.httpcookie.aspx

Full documentation for the .Net class System::Web::HttpCookieCollection can be found at https://msdn.microsoft.com/en-us/library/system.web.httpcookiecollection.aspx

Full documentation for the .Net class System::Collections::Specialized::NameValueCollection can be found at https://msdn.microsoft.com/en-us/library/system.collections.specialized.namevaluecollection.aspx

 

AlphaLaunch - Install Mobile Apps to Apple and Android Devices - AlphaLaunch is a free AppStore app that you can install on an Android or Apple device. Once AlphaLaunch has been installed on a device you can install as many Apps as you want to that device without having to go through the Apple or Android App stores, or without having to go through a PhoneGap build process (either Adobe PhoneGap Build or the Command Line Interface). The Apps are installed into AlphaLaunch, not directly to the device. This makes it extremely easy and quick to install new Apps on a device.


Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4

 

NOTE: AlphaLaunch is not licensed for use in a production environment if you do not have a subscription to the Enterprise Edition of Alpha Anywhere.

 

The use cases for AlphaLaunch include:

Once an App has been installed into AlphaLaunch it operates largely identically to the way in which it would operate had it been installed directly on the device. For example, even when there is no internet connection, you will be able to start any App that is installed in AlphaLaunch.

AlphaLaunch is not suitable as a means of deploying a public facing App that will be installed by many users who will go to the App Store to find and install your App. When an App is installed directly onto a device the App icon will appear on the device's home screen. However, when you publish to AlphaLaunch, the App will not have an icon on the home screen. To launch the App you will first have to launch AlphaLaunch and then you will be able to select the App from the list of Apps installed in AlphaLaunch.

 

NOTE: Apps installed in AlphaLaunch are PhoneGap applications (even though you did not have to go through the PhoneGap build process) and they can use any of the PhoneGap plugins that AlphaLaunch exposes. For more information see the section Understanding AlphaLaunch Limitations below.

NOTE: On Apple devices, there are other ways that you can allow a user to test an App that you are developing using the Apple Test Flight system. However, setting up Test Flight is complex. Alternatively, you could get the UDID of a user's device and use a special Apple publishing profile with PhoneGap build that allows Apps that you build to be installed on that user's device  (without having to submit the App to the App store). However, this too, is complex and you are limited to only 100 devices.

 

Understanding AlphaLaunch Limitations

To see the list of plugins that AlphaLaunch enables, tap the Settings button in the footer of the AlphaLaunch home screen.

Then make sure that the Show Support Settings switch is on.

 

 

 

Then scroll the screen till you see this menu item:

 

 

How to Install AlphaLaunch on a Device

To install AlphaLaunch on a device, simply go to the App Store and search for 'Alpha Launch'.

 

How to Run an App That Has Been Installed in AlphaLaunch

To run an App that was previously installed in AlphaLaunch, simply launch the AlphaLaunch App on your device by clicking the Launch icon.

 

Then scroll the list of installed Apps until you find the App that you want and tap on the App name.

 

How to Install An App Into AlphaLaunch

To install a new App into AlphaLaunch, tap the Manage/Add button in the footer of the AlphaLaunch App.

 

If there are any existing installed Apps a screen showing these apps will be shown.

Note that for each installed App, the name of the server from which the App was installed is shown. When an App is run, all Ajax callbacks are made to the same server from which it was originally installed.

 

'

 

You can use this screen to reorder the installed Apps. You can also use a 'press-hold' gesture on any of the Apps in the List to bring up a screen that will allow you to uninstall an App or to update the App.

Tap the Add button to  bring up a list of the available Apps on the server that AlphaLaunch is currently configured to use.

For each App that is listed, there is either an Install or Reinstall button. The Install button will appear if the App is not currently installed and the Reinstall button will appear if the App has previously been installed. Reinstalling a previously installed App is effectively updating the App to a newer version of the App.

 

 

 

How to Select the Active AlphaLaunch Server

When you click the Add button on the Manage App List screen, the Apps that are available on the active AlphaLaunch server are shown. You can change the active AlphaLaunch server by tapping the Settings button at the AlphaLaunch home screen.

 

Then, tap on 'Server Web Address for Downloading Apps....

 

This will bring up the list of registered servers.

 

Tap on the server you want to select, then tap the Select button.

 

NOTE: The Active AlphaLaunch server only controls the list of available Apps that you can install when you press the Add button to install a new App. If an App (called 'App1' for example) was installed from 'Server1' and then the active server is changed to 'Server2', when App1 is running, it will make Ajax callbacks to 'Server1', regardless of what server is currently designated as the 'active' server.

 

 

How to Register a New AlphaLaunch Server

 

To register a new AlphaLaunch server, follow the instructions (above) for selecting the Active AlphaLaunch server. On the Server List screen (shown above), tap the Add button.

This will bring up the Edit Server Info screen where you can either type in the server address or scan a special QR code that encodes all of the necessary information.

 

 

 

How To Publish an App to AlphaLaunch

 

To publish Apps to AlphaLaunch open the Web Control Panel and select the project that contains the Apps that you want to publish.

NOTE: An 'App' is a UX component. The UX component can call child UX components, but these child UX components should typically be configured as Precomputed so that they can load directly from the device (so as not to be dependent on an Internet connection).

 

Before you publish Apps to AlphaLaunch you must first 'register' the Apps you want to publish. Registering an App involves defining how the App will appear when it is shown in the AlphaLaunch home screen and how it will be described when a user displays the list of available Apps that can be installed into Alpha Launch

 

Registering Apps To Be Published to AlphaLaunch

To register the Apps from a particular Web Project for publication to AlphaLaunch, tap the More... button on the extreme right of the Web Control Panel.

 

 

Then select the AlphaLaunch, Publish Apps to AlphaLaunch... menu item.

 

 

This will bring up the AlphaLaunch dialog where you can register the Apps from the Web Project that you want to publish to AlphaLaunch.

 

 

To register a new UX component, click the Add component button and then select the UX component you want to publish.

 

 

The AlphaLaunch dialog will then show the component that you selected and the orange icon will indicate that the settings for this component have not yet been defined.

Either double click on the component name, or click the Edit component settings button to open the AlphaLaunch Settings dialog box.

 

 

The important properties on this dialog include:

 

 

You can preview how the App will appear in the AlphaLaunch home screen by clicking on the Preview app template hyperlink at the bottom of the screen.  For example, here is a preview of a template that is using a purple background color and an SVG icon.

 

 

Once you have registered all of the Apps in a Web Project that you want to publish to AlphaLaunch you are now almost ready to publish to AlphaLaunch.

But before you can publish you must first define a Publishing Profile that indicates where the Apps will be published (i.e. the Alpha Anywhere server and folder on that server where the Apps will be published). To define a publishing profile, click the Profiles button on the toolbar when the Web Project Control Panel has focus.

 

 

 

NOTE Each Web Project will typically be published to its own AlphaLaunch server address. For example, you may have 3 UX components in 'Web Project1' that you want to publish to AlphaLaunch and (say) 2 UX components in 'Web Project2' that you want to publish to AlphaLaunch. In both cases you may want to use the same physical Alpha Anywhere server. The Publishing Profile that you define for 'Web Project1' might specify that you want to publish to a folder called 'webProject1', in which case the server address for the 3 Apps in this group of Apps might be something like 'http://www.myAAserver/webProject1'. On the other hand, the Publishing Profile you define for 'Web Project2' might specify that you want to publish to a folder called 'webProject2', in which case the server address for the 2 Apps in this group of Apps might be something like 'http://www.myAAserver/webProject2'.

 

 

Once you have defined the publishing profile, click the Publish Apps to AlphaLaunch Server button on the AlphaLaunch dialog.

 

This will bring up the Publish to AlphaLaunch dialog. You will need to select the Publishing Profile to use and you will also need to specify the Sever URL (i.e. the url of the location where the Apps are being published).

 

Once you have published your Apps you will need to register the server in AlphaLaunch. AlphaLaunch will contact the server to get a list of the available Apps.

For instructions on how to register a server with AlphaLaunch, see the section above titled How to Register a New AlphaLaunch Server . To make it easy to register a new AlphaLaunch server (i.e. to avoid having to type in a long server URL on a mobile device keyboard), you will probably want to generate a QR code with with server address. Check the 'Show a QR code...' property before you click the OK button.

 

 

 

 

You can use Advanced mode when you want to republish to AlphaLaunch after having made a change to the App settings (e.g. the App template, description, version number, etc.), but not the App itself. This will speed up the process of publishing the Apps because it will avoid having to recreate the static fileset for each App.

 

 

 

Adding an Exit Button to your App

When an App is run in AlphaLaunch you will typically want to add an 'Exit' button to your App to go back to the AlphaLaunch home screen. If you do not add an Exit button, then after the user launches the App they will not be able to get back to the AlphaLaunch home screen to launch a different App.

You can use Action Javascript to add an Exit button, or you can code the Javascript for the button yourself.

To use Action Javascript, select the 'AlphaLaunch Actions' action for the list of available Action Javascript actions.

To code the Javascript directly, use this code:

if(A5.shell) {A5.shell.exitComponent();};

 

The code tests if you are running in AlphaLaunch, then if you are then it calls the A5.shell.exitComponent() method.

 

Troubleshooting

The most common problem with AlphaLaunch is that after you have published Apps to your AlphaLaunch server and you then go to AlphaLaunch to install the Apps you just published, the Apps are not listed on the Apps to Install screen. This cause of this problem is either the Application Server has not been started, or the Server Addrtess (i.e. URL) that was entered in the Publish to AlphaLaunch dialog was incorrect.

You can test if you entered a valid server address by going to a browser and entering the following URL into the browser

 

<server URL>/availableAppInfo.txt

 

 For example, if your server URL was entered as:

http://192.168.70.157/AlphaLaunchDemo

You would enter this address into the browser address bar:

http://192.168.70.157/AlphaLaunchDemo/availableAppInfo.txt

 

 

If you do not receive a response, then it is likely that the server URL that you specified is incorrect.

 

App Install Errors

If you are installing an App from a folder on an Alpha Anywhere standard server (as opposed to the Alpha Anywhere Server for IIS), you might get an install error if the App has a large number of files. This is because the Alpha Anywhere server limits the number of files that can be simultaneously served. The error will not occur if you are using the Alpha Anywhere server for IIS. You can work around this problem by copying the folder that contains your App files to a bucket on Amazon S3 and then setting the Download location for the App to the URL of this S3 bucket.

 

AlphaLaunch Methods

 

 

A5.shell.exitComponent() -- Exit the App that is running an return to the AlphaLaunch home screen

A5.shell.getAppDir() - Returns the file URL of the local directory with the App's files

A5.shell.getAppFileStorageDir() - Returns the file URL of the local directory where the Apps data files are stored (this is separate from other Apps).

 

UX and Grid Component - Language Definitions - High Order Characters - When you tag strings in a Grid or a UX with language tags (<a5:r> ...</a5:r> you must then define how the tags are resolved in each of the different supported languages. Previously when entering high order characters, it was necessary to HTML encode the character. Now you can just type in the characters directly into the Language Definition dialog box.

 

 

UX Components - Pre-render - Working Preview - Internet Explorer - jQuery - When you do a Working Preview of a UX component and all of the following conditions are met:

then jQuery will not be loaded.

If you need to have jQuery loaded while you are in Working Preview then you can either switch to Chrome for Working Preview, or change where jQuery is loaded from.

If you cannot switch to Chrome for Working Preview, and you cannot change the location from which jQuery is loaded, then you will have to make an Ajax callback to load jQuery. For example, you could use the following Xbasic function to handle the Ajax callback that loads the internal version of jQuery.

 

function loadJQuery as c (e as p)
    loadJQuery  = __hidden__javascript__a5_jquery_core() + crlf() + __hidden__javascript__a5_jquery_ui()
end function
 

 

Xbasic Function Libraries, Modules and Classes - Encrypt - Password Protect - When you create Xbasic Function Libraries, Modules or Classes in your Web Project you can now specify that the files should be encrypted, or both encrypted and password protected.

In order to encrypt a file the first line of the file must be an Xbasic comment (with no leading spaces):

'ENCRYPT

 

In order to both encrypt and password protect a file the first line of the file must be an Xbasic comment (with no leading spaces) of this form:

'PASSWORD:your_password

 

For example:

'PASSWORD:mysecretpassword

 

At run-time encrypted files are automatically decrypted.

If a file is password protected, then when you try to edit the file from the Web Control Panel, you will be prompted to enter the password. Once you have successfully supplied the file password you will no longer be challenged for the password when you next edit the file (until you exit from the Alpha Anywhere IDE).

 

.Net v4.6.2 - The Alpha Anywhere Installers now install .Net V4.6.2 if it has not previously been installed. Previously, the installers were installing v4.6.1

Bugs

UX Component - List Control - onSelect Event - Detail View - If a List had a Detail View and the List was configured to Allow Null Selection, when the List was rendered, the onSelect event would fire, even though no row in the List was selected.

UX and Grid Component - Action Javascript - File Download - International Characters - If the filename of the file to download contained international characters, the download would fail.

UX Component - Action Javascript - SQLite Actions - Create Table From Data Action - If the Create Table From Table action was configured to get the data by making an Ajax callback, if the data returned by the callback contained null values or values with double quotes, the action would fail.

UX Component - Google Maps - The API for scaling bitmaps uses as markers on a map was changed by Google. Support for the new API has been added.

UX Component - List with Detail View - Sync Log - The sync log feature was not working.

UX Component - List Controls - .dbf Tables - Mapped Table - If a List control was based on .dbf tables and if any of the .dbf tables in the databasource definition was a mapped table that included date fields, an error was generated.

UX Components - jQuery - Pre-rendered - If a UX component was set to pre-render and jQuery was specified to be loaded then in Live mode, jQuery was not being loaded. In Working Preview, jQuery was loaded (as long as you were using Chrome for Working Preview).

NOTE: For pre-rendered UX components that are set to load the internal version of jQuery that are rendered in Working Preview using Internet Explorer, jQuery is not loaded.

UX Component - PhoneGap - Action Javascript - Image Capture for List Detail View Action -  onImageCapture Event - The onImageCapture event was not firing if the image was captured using using PhoneGap

UX Component - PhoneGap - App Icons - The utility to create app icons in the PhoneGap builder was failing. if you have not installed your own copy of ImageMagick. This is now fixed.

Desktop Applications - Forms - MS Word Mailmerge - Was failing if the merge data contained a double quote.

SQL Server Reporting Services - Fixed an issue with multi-value input parameters.

UX Builder Crash - If all of the following conditions were met, then when doing a Working Preview of a component, Alpha Anywhere would crash

Web Applications - Multi-file Upload - If you created your own .a5w page to do file uploads, the multiple attribute in the <input> element was not handled properly.

Consider the following .a5w page. Notice that the <input> element uses the multiple attribute. Therefore, the control name must end in [] to indicate that multiple instances of this variable must be created (i.e. the variable must become an Xbasic array when the form is processed).

 

<form action="fileupload.a5w" method="post" enctype="multipart/form-data">
    Select images:

    <input type="file" id="files" name="selectedfile[]" multiple>
    <input type="submit">
</form>
 

When the files are uploaded, the above example specifies that an .a5w page called fileupload.a5w page will be called. Here is an example of how the fileupload.a5w page might be defined:

<%a5
dim files as p
files = request.variables.selectedFile

'files will be an array. the number of items in the array will match the number of files that were selected

'save each uploaded file to a folder

'ensure that the folder exists

dim folder as c

folder = "c:\uploads"

dir_create_recurse(folder)

 

dim count as n

'get a count of the number of files that were uploaded

count = files.size()

dim i as n

 

'loop over each item in the files[] array

dim fn_i

for i = 1 to count

    'construct the local filename

    fn_i = folder + chr(92) + files[i].filename

    'each file in the array has a SaveToFile() method

    'call this method to persist the uploaded file to a local file

    files[i].saveToFile(fn_i) 

next i
 

'Note: Each item in the files[] array will have these properties and methods:

'Properties:
    'Name
    'FileName
    'ContentType
    'CharacterSet
    'Encoding
    'Data - the data that was uploaded.

        'NOTE: It is recommended that you do NOT reference the 'data' property (especially for large files)

        'as it causes the data to be read into memory.
    'Size
'Methods

    'SaveToFile - save the uploaded data to a local file
    'SaveToStorage - save the uploaded data to storage (e.g. S3, Azure, Disk, etc.)
%>

 

Tips

Grid Component - Detail View - Disable Input Controls when Update Not Allowed - In a Grid component if you have the Security Framework enabled and the user does not have permission to update data, the input controls are still enabled even though the user will not be able to save any edits.

It might be desirable to disable input controls when the user does not have update permission.

Here is how this can be done:

First, define the following Javascript function in the component's Javascript Functions property:

 

function enableControl(alias) {

    var obj = window[alias + '_GridObj'];
    var val = obj._editPermissions.allowUpdate;
    return val;
}

 

Next, add the following expression for the client-side Enable expression for each of the Detail View input controls:

 

enableControl('{grid.componentName}')

 

NOTE The enableControl() function takes the Grid alias as an input parameter.  This allows the Grid object to be dynamically computed. If the enableControl() function had used:

{grid.object}._editPermissions

Then you would run into trouble if you had multiple Grids that defined the function because the last Grid that was displayed would overwrite the previously defined global function and the {grid.object} placeholder would resolve to the last Grid displayed.

 

Web2Cal Calendar Control - Adding Server Side Event Handlers To Respond to Event Changes -

When using the Web2Cal calendar control you might want to execute server-side code for the following events:

There are no built-in hooks for these events, but you can easily define you own.

For the event added, edited, or deleted cases, you can add event handlers as follows:


function onEventDelete as v (e as p)
end function 
function onEventUpdate as v (e as p)
end function 
function onEventAdd as v (e as p)
end function

 

How to Update the afterDialogValidate Event Handler Function
Make the changes shown in red to the afterDialogValidate  event.

'update the event on the calendar
dim javascriptUpdateCalendar as c
dim po as p
if pv.eventsMode = "EditEvent" then
    po.eventId = convert_type(e.dataSubmitted.eventId,"N")
    onEventUpdate(e)
else
    po.eventId = eventId
    e.eventId = po.eventId
    onEventAdd(e)
end if

 

To handle the event is moved case, edit the Web2Cal component and add this code to the onComponentExecute server-side event:

if eval_valid("request.variables._XbasicFunction") then 
	if request.variables._XbasicFunction = "updateEvents" then 
		'event was moved -- event data is in request.variables._calEvent_eventId, etc.
	end if 
end if 

 

 

 

 

Alpha Anywhere V4.4.3 - Build 4254-4863 04-Apr-2017

Features

Xbasic - a5_json_to_excel() Function - Export JSON Data to Excel - Exports data in a JSON document to an Excel file. If the JSON document is an object with multiple arrays, each array is exported as a separate sheet in the Excel file.

If the JSON document is an array, the Excel file will have a single sheet called 'Table1'

Syntax:

L flag = a5_json_to_excel(c Json, c filename)

Where

 

For example, if the JSON document shown below was exported to Excel, the Excel file would have two sheets ('customers' and 'phoneNumbers'). Each sheet would have the data in the corresponding array in the JSON data.

			{
	"customers" : [
		{"id": "1", "firstname" : "Fred", "lastname": "Jones"},
		{"id": "2", "firstname" : "Mary", "lastname": "Nickerson"}
	],
	
	"phoneNumbers" : [
		{"id": "1", "type" : "Home", "number" : "555-555-1234"},
		{"id": "1", "type" : "Office", "number" : "555-555-1235"},
		{"id": "2", "type" : "Home", "number" : "555-555-1236"},
		{"id": "2", "type" : "Office", "number" : "555-555-1237"},
		{"id": "2", "type" : "Vacation", "number" : "555-555-1238"}
	]
}


			

TabbedUI - onLogin Server-side Event - This event can now set data values that will be available when the client-side afterLogin event fires.

For example, you could add this code in the server-side onLogin event:

e.eventDataObject = "{userName: '"+e.userName+"', var2: 'some other value', timeOfLogin: '"+js_escape("" + now())+"'}"
 

In the client-side afterLogin event you can refer to any value in the eventDataObject.

 

For example:

alert('Welcome: ' + e.eventDataObject.userName );
 

Reports - Free-form Reports - Vertical Lines - Growable - You can now set the Growable property on vertical lines in a report. When this property is set, the vertical line will grow to the full height of the report section it is in.

 

 

For example, in the report shown below, the vertical line extends the full height of each record in the Detail Section without any gaps between the lines.

Bugs

Application Server for IIS  - Password Expiration - When publishing an application to IIS, if the application has a password expiration set, the expiration time will not be set correctly and can lead to users getting password has expired messages.
 

UX Component - List Control - Detail View - Parent-Child Lists - New Records - If you entered a new record in a child List and then synchronized the data, if focus was on the new child record at the time the sync command was executed, focus did not remain on this record when the sync completed.

Reports - SQL Data Sources - Null Values - Fixed an issue with character fields that had null values.

Reports - SQL Data Sources - Long Text - Fixed an issue with long text fields not printing all of the data in the field under some circumstances.

 

 

Alpha Anywhere V4.4.1 - Build 4246-4859 31-Mar-2017

Videos

UX Component - List Control Showing Content in Row When Row Is Selected A common use case with the List is to only show certain content in each List row when the row is selected. This is easily done using CSS.

In this video we show how this is achieved.

Watch Video
Download Component

Date added: 2017-03-26
     

Features

Alpha Anywhere Application Server - TLS Protocol - The Alpha Anywhere Application Server now allows the server administrator to specify the minimum TLS protocol version supported. While SSL v2 and SSL v3 had been fully removed from the Alpha Anywhere Application Server some time ago, it has not been possible to fully disable older TLS versions until now. This setting allows TLS 1.0 and TLS 1.1 to easily be completely turned off, if desired.

TLS 1.2 is the most recent protocol and generally considered to be the most secure. Setting the minimum TLS version to 1.2 will disable TLS 1.0 and TLS 1.1 and provide what is currently considered the highest level of security. Note however that not all older web browsers or operating systems support TLS 1.2. Site administrators should evaluate the needs of their users before modifying this setting.

This setting defaults to TLS 1.0, in order to prevent unexpected client connectivity issues.

 

Bugs

Reports - SQL Reports - Null Numeric Values - Null numeric values were being displayed as 0 and not blanks in reports. This bug was introduced in v4.4.0.

Xbasic - AlphaDAO - SQL Server - In certain cases, when listing tables in a SQL Server database, the 'dbo' schema prefix was added to all of the tables that were listed. This was not necessary and now when tables are listed, the 'dbo' schema prefix is not shown in the list of tables.

UX Builder - Duplicate Control - A bug was introduced in the Duplicate Control command in V4.4.0.

Application Server - Server Settings Dialog - Dialog Height - The OK and Cancel buttons were not visible on machines with less than 800 pixels vertical resolution. This issue was caused because the new Administrative Alerts feature (introduced in V4.4.0) caused the dialog height to increase in size. The Alerts properties have now been moved to their own tab in the dialog.

 

 

Alpha Anywhere V4.4.0 - Build 4238-4856 28-Mar-2017

 

 

Videos

UX Component Alignment Container The Alignment Container makes it easy to Left, Center or Right align a series of control on a UX.

Watch Video

Date added: 2017-02-02
Xbasic Using Xbasic Classes in Server-side code You can define Xbasic classes in your project and then use those classes in any server-side Xbasic code.

In this video we show how an Xbasic class definition can be added to a web project and then used in the server-side code that executes when an Ajax callback is made.

Watch Video

Download Components

Date added: 2017-02-11
UX Component - Map Control Adding Multiple Markers to a Map Control using Client-side Data Action Javascript has an action to add multiple markers to a map. The data that defines the latitude/longitude for each marker on the map (and also for the marker titles, details etc). can either come from server-side data, or from client-side data.

In the case of server-side data you specify the name of a Data Series that specifies the properties for each marker.

In this video we show how to configure the Action Javascript 'Add multiple markers to a map' action to use client-side data. This client-side data can come from a Javascript function, a List control, the client-side Data Cache, or, in the case of a PhoneGap application, by querying a SQLite database on a device.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4
Watch Video - Part 5

Download Component

Date added: 2017-02-12
UX Component - FormView Control Lookup Fields When you create a FormView control, you might want to display 'friendly' values for some of the fields in the form. For example, you might want to display the Product Name, rather than the Product Id.

In this video we show how you specify a lookup for any field in the Form View control.

Watch Video

Download Components

Date added: 2017-02-14
UX Component - PhoneGap Using the CLI (Command Line Interface) to Build PhoneGap Applications instead of PhoneGap Build When you build a PhoneGap application from a UX component that you have built, the easiest approach is to use the Adobe PhoneGap Build service. Direct integration with PhoneGap Build is built into the Alpha Anywhere IDE. While the advantages of using PhoneGap Build are clear - no software to install on your PC, and ability to build apps for iOS on your Windows machine - there are also disadvantages. These include having to wait an uncertain amount of time before PhoneGap Build finishes the build (wait time depends on how busy the service is) and inability to use certain plugins not supported by PhoneGap Build.

Another way in which PhoneGap applications can be built is by using the PhoneGap CLI (Command Line Interface). When you use the CLI, you are not restricted to only the plugins supported by PhoneGap build. The disadvantage of the CLI approach is that you will first have to install the CLI tools and platform SDKs on your machine. You will also need a Mac to build for iOS.

In this video we give an overview of using the CLI.
Watch Video
See documentation

Date added: 2017-02-18
UX Component Using 3rd Party jQuery Libraries in Control Javascript The UX Builder allows you to define 'Control Javascript' which allows you to easily configure a UX control to use a jQuery controls (such as a date or time picker). However, in the case where the jQuery control is defined in a linked file, you can run into timing issues that result because the control javascript is executed before the linked jQuery file has loaded.

This video describes how you can resolve these timing issues.

Addendum: In the video we show that the control javascript function is created using the syntax:
var clockpicker = function()
This should be changed to window.clockpicker = function()

Watch Video

Date added: 2017-02-19
TabbedUI Adding a Search Feature to the TabbedUI It is not uncommon for developers to create TabbedUI components with a very large number of items. Users may then struggle to find a particular item in the list of available menu items. Adding a search feature to the TabbedUI component makes it very easy for users to find the menu item they want.

In this video we show how the search feature is added to the TabbedUI component.

Watch Video

Date added: 2017-02-24
Reports Using SQL Server Reporting Services Reports in an Alpha Anywhere Project Many organizations who use SQL Server also use SQL Server Reporting Services (SSRS). Using reports created in SSRS in an Alpha Anywhere project is possible.

In this video we show how reports defined in SSRS can be used in Alpha Anywhere applications.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Date added: 2017-02-25
Node Calling a Node Service that Returns Binary Data When you call a Node service from Xbasic, the service can return both text and binary data.

In this video we show how a Node Service can return binary data.

Watch Video

Date added: 2017-02-28
UX Component Running Asynchronous Functions Synchronously Many Javascript functions in an application are asynchronous. For example, functions that make Ajax callbacks are asynchronous and many PhoneGap functions are also asynchronous. Often you will want to call several asynchronous functions, but you want to execute the functions synchronously. For example, you do not want to call the second function until the first function has completed.

Javascript Promises are typically used to run asynchronous code synchronously. But Promises can be hard to understand and it can be tricky to restructure your code to use Promises. The Alpha Anywhere Javascript library has a function called A5.runChain() that provide an easy way to run asynchronous functions synchronously. Also, minimal changes need be made to your function definitions to make them suitable for use with the A5.runChain() function.

In this video we show how the A5.runChain() function is used.

Watch Video - Part 1
Watch Video - Part 2


Date added: 2017-03-04
UX Component Semi-circular Number Display Control The semi-circular number display control displays the value of a number on a semi-circular chart. It is ideal for dashboard type applications.

This video shows how you can add a semi-circular number display control to a UX component and how you can configure the component.

Watch Video - Part 1
Watch Video - Part 2

Download Component

Date added: 2017-03-04
UX and Grid Component Code Glossary The code glossary is a great timesaver when editing Xbasic and Javascript code.

In this video we show how to use the code glossary in the editors.

Watch Video

Date added: 2017-03-17
UX Component - Javascript Charts Introduction Javascript Charts allow you to create a variety of different chart types using Javascript. Because the charts are created client-side, using Javascript, these types of charts are ideal for disconnected applications where the Chart control cannot be used (as this control type produces charts server-side).

In this video we show how to set up a basic Javascript Charts.
Watch Video

Date added: 2017-03-26
UX Component - Javascript Charts Binding Chart Data to a Javascript Function The data shown in a Javascript Chart can be obtained by calling a Javascript function.

in this video show show how to bind the Chart data to a Javascript function.

Watch Video
Download Component

Date added: 2017-03-26
UX Component - Javascript Charts Binding Chart Data to Data From a SQL Database - Using a Data Series for Chart Data The data shown in a Javascript Chart can be obtained by querying a SQL database.

In this video show show how to bind the Chart data to data from a SQL database table by binding the Chart data to the data in a Data Series. The Data Series is populated with data from a SQL database table.

Watch Video

Date added: 2017-03-26
UX Component - Javascript Charts Binding Chart Properties to a Javascript Function Any property of a chart can be made dynamic by binding the property to the result of a Javascript function.

In this video we show how properties of the Chart  (in addition to the Chart data) can be made dynamic.

Watch Video
Download Component

Date added: 2017-03-26
UX Component - Javascript Charts Action Scripting Methods for Working With Javascript Charts Action Scripting exposes several methods for working with Javascript Charts.

In this video we show how you can use Action Scripting to resize a Javascript Chart.

Watch Video
Download Component

Date added: 2017-03-26
UX Component - Javascript Charts Action Scripting - Setting a Chart Property Using Action Scripting vs. Binding a Chart Property to a Javascript Function Action Scripting allows you to dynamically change properties (such as the Chart colors, or title) after the Chart has been rendered. However, you can also achieve the same result by binding the Chart properties to Javascript functions.

In this video we contrast the two methods for setting Chart properties.

Watch Video - Part 1
Watch Video - Part 2

Download Component


Date added: 2017-03-26
UX Component - Javascript Charts Using Action Scripting to Refresh Chart Data Action Scripting allows you to refresh the data shown in a Chart. If the Chart data is based on a Data Series, an Ajax callback to the server will be made to refresh the data in the Data Series on which the Chart depends and then the Chart will be redrawn, showing the new data.

In this video we show how Action Scripting is used to refresh the Chart data.

Watch Video

Date added: 2017-03-26
UX Component - Javascript Charts In Depth Example - Chart Based on SQL Data This example shows a pie chart whose data is obtained from a multi-table SQL query against the sample Northwind database. The Chart is based on a custom Data Series to generate the Chart data. The user can select the country for which the Chart should be shown from a dropdownbox control.

In this video we show how this Chart is set up.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Download Component


Date added: 2017-03-26
UX Component - Javascript Charts Understanding the Structure of the Javascript that Defines a Javascript Chart The Javascript used to define a Javascript Chart has a well defined structure, described in this video.

Watch Video

Date added: 2017-03-26
UX Component - Javascript Charts Javascript Chart Events In this example we show a Chart with a Tooltip event. After the Chart is resized, the Tooltip events must be re-registered.

Watch Video
Download Component


Date added: 2017-03-26
     

Features

UX Component - Copy/Paste Controls - The UI for copying and pasting controls has been simplified.

Grid, UX and TabbedUI Builder - Collapse/Expand Property Grid Categories - You can now quickly collapse or expand all categories in the Property Sheets. This can make it easier to find a property without having to open the Properties search dialog.

 

 

PhoneGap App Builder - Icons and Splash Screens - The way in which icons and splash screens (iOS calls them launch images) has been completely rebuilt and a new option has been added to the Application Master Image Resources category that allows you to generate a series of 9-patch splash screen images for Android devices (iOS does not support 9-patch images without additional libraries).



 

VERY IMPORTANT: It is very important that you create a new PhoneGap Project when generating custom icons and splash screens for your app because the PhoneGap app config.xml file has been changed to support new functionality.

When you supply a single image that needs to be resized for the numerous aspect ratios required by all of the different types of mobile devices, the aspect ratio will typically change and the resulting image will be out of proportion. The new resizing code uses a center weighting technique to clip the image without any change to the image aspect ratio. This technique is used for the generation of all of the splash screens and you need to be aware of that when you supply the images for the portrait or landscape orientations.
 

Recommended Image Sizes
For portrait splash screens, the recommended size is 1536px x 2048px.
For landscape splash screens, tre recommended size is 2048px x 1536px.
You can also specify a square image (suggested size is 2732px x 2732px) for both orientations and the resulting images will not be distorted.

Android 9-patch images
A 9-patch image is a standard png file that has been divided into a matrix of 3 x 3 rectangles (like a tic-tac-toe board). Each region in the matrix has specific stretch properties that allow the image to be resized without altering the aspect ratio of the center weighted rectangles. As such, 9-patch images can be stretched to fit the different screen sizes without clipping or distortion. You need to supply a square image that will be used for both portrait and landscape modes and the graphics need to be center weighted. The recommended size is 2732px x 2732px.

For more info on 9-patch splash screen images see: Cordova Splashscreen Plugin Documentation

 

NOTE:  iOS Storyboard Launch Images -  If you open and inspect the new config.xml file you will see support for iOS storyboard launch images (which act much like Android's 9-patch images). While the support is included in the image builder module, it hasn't been exposed because the current version of PhoneGap Build does not support it. As soon as PhoneGap Build supports the inclusion of iOS storyboard images, we will expose iOS storyboard support within the PhoneGap App Builder.

PhoneGap App Builder - Use ImageMagick Option -  This option has been removed as all icons and splash screens are now generated using ImageMagick.

 

 

UX Component - List Control - deselectAll() Method - A new method has been added to the List control to un-select all selected rows in a List.

Contrast this method with the low level ._deselectAll() method which also un-selects any selected rows in a List, but does not perform any action on child Lists or the associated Detail View that the List may have..

The .deselectAll() method wraps the ._deselectAll() method, but in addition to un-selecting rows in the List, if the List has child Lists with pre-fetched data, the selected rows in all child Lists are also un-selected, and the Detail View for the List (and the Detail View for any child Lists with pre-fetched data) is disabled (if the 'No record in List selected' property for the top-most parent List is set to 'Disable Detail View').

For example:

var lObj = {dialog.object}.getControl('CUSTOMERLIST');

lObj.deselectAll();

 

 

UX Component - Data Series - Publish to Client-side - You can now specify that the data in Data Series should be published to the client-side so that it can be used in your Javascript code.

You define Date Series either by clicking on the smart field for the Data Series property (on the UX Builder Properties pane) , or by click on the Menu button.

 

 

 

 

Your Javascript code can reference the data in a Data Series using the following syntax:

{dialog.object}._dataSeriesData.SeriesName.SubSeriesName

 

If the Data Series has no sub-series, then syntax for referencing the Data Series is:

{dialog.object}._dataSeriesData.SeriesName

 

 

 

Understanding Data Series

A Data Series is a series of values. Say you have a SQL query that returns the data shown in the table below.

Each column in the table is a series of data. For example, the data series in the pink Firstname column is

Fred, John and Sally.

 

Firstname Lastname Age
Fred Smith 23
John Jones 35
Sally Harrison 29

 

The name of the Data Series represented by the pink column in the above table is:

Names.Firstname

 

(where 'Names' is the arbitrary name given to the data table)

 

A common use case for Data Series is in charting applications. Both the Chart and Javascript Chart control in the UX component consume data series for the data shown in the charts.

 

Action Javascript

There is a new action in Action Javascript to perform actions on Data Series. The Data Series Actions action allows you to:

 

UX Component - Javascript Charts - A new option for generating charts in the UX component is now available. Javascript Charts generate charts using client-side data. Because Javascript Charts are generated using Javascript with client-side data, they are ideal for disconnected mobile applications.

 

 

NOTE: Javascript charts are based on the open source RGraph charting library. Only the SVG charts in this library are built into Alpha Anywhere. If you want to use any of the Canvas charts in this library, you can, but you will need to write the Javascript yourself.  For more information go to http://www.rgraph.net.

 

Contrasting Javascript Charts with the Chart Control

The Chart controls is a server-side control. The chart is rendered as a bitmap on the server and then the client-displays the bitmap image. Because the Chart control is a server-side control, it is not suited for disconnected applications. Also, since the Chart control is a server-side control, it will be slower than Javascript Charts.

To add a Javascript Chart to a UX component, select the [Javascript Chart] control in the Other controls section of the UX toolbox.

 

 

NOTE:  Tthe Chart control (i.e. the server-side charting control) is available in the Data Controls section of the UX toolbox.


 

 

 

After you add a Javascript Chart to your UX, you can then edit the Javascript Chart properties by clicking the smart field for the Chart properties property.

 

 

This will open the Javascript Chart builder, as shown below.

The top half of the screen is where you enter the Javascript code that generates the chart and the bottom half of the screen allows you to get a quick preview of the Chart.

In most cases you will get a quick start by selecting one of the Sample Charts. This will enter the Javascript for the selected chart and you can then tweak the Javascript to get the chart appearance that you want. You will likely also want to base the chart on real data, not the sample data shown in the sample chart.

 

 

To select a sample chart, click the Select Sample Chart button. This will open up a dialog showing the available sample charts:

 

 

Select the sample chart that you want. It will then fill in the Javascript for that chart into the builder. For example:

 

 

The Javascript shown in the window is the Javascript used by the RGraph charting library to render the Javascript chart.

 

Understanding the Pattern Used for the Chart Javascript

All of the sample charts insert Javascript that follows the same pattern.

 

var _settings = function() {

        //function that returns an RGraph settings object

}

var _chart = new RGraph.SVG.Bar(_settings()).draw()

 

{dialog.object}._jsCharts['{chartName}'] = {};
{dialog.object}._jsCharts['{chartName}'].settings = [_settings];
{dialog.object}._jsCharts['{chartName}'].object = [_chart];
 

 

Depending the RGraph chart type (e.g. Pie, Line, Bar, etc.), the appropriate RGraph function is called to render the chart.

A settings object is passed to the RGraph function. This settings object is created by calling the _settings() function.

NOTE: You do not need to include the RGraph charting Javascript libraries yourself in your UX component. The libraries are automatically loaded by Alpha Anywhere.

The Chart settings are stored in the _jsCharts object in the UX component object. These settings are stored to enable the chart to be refreshed with new data, to be changed on the fly by changing any of the chart properties, or to be dynamically resized. Notice that the settings object and the object object are arrays. This is because a chart can actually be composed of multiple charts each drawn on the same DIV.

The Javascript for the chart uses two special placeholders:

 

 

Using Real Data in a Chart

When you select a Sample Chart, the Javascript that is inserted into the Javascript window in the Javascript Chart builder uses static data. This is fine initially when you are designing a chart, but at some point you will want to replace the static sample data with 'real' data.

The source of this 'real' data must be client-side data. For example, it might be data from a column in a List control. You will need to create a Javascript function that gets the data from the List and then set the data property in the Chart settings to the this function.

In many cases the 'real' data will be data that you want to get by querying a database, calling a service (REST, SOAP, etc.), or running some custom server-side code. In the case where the data you want to use in your chart originates on the server, you will need to define a Data Series that retrieves the necessary data. (When you define the Data Series you will need to specify that the Data Series data should be 'published' to the client-side.)

For example, here are the settings for a simple bar chart that uses static sample data:

var _settings = function() { 
   var settings = {
      id: '{chartDiv}',
      data: [8,5,9,3,5,2,4],
      options: {
          gutterTop: 50,
          hmargin: 20,
          xaxisLabels: ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'],
          tooltips: ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'],                
          title: 'A basic Bar chart',
          titleSubtitle: 'A chart showing daily values for a week',
          titleSubtitleItalic: true,                
          colors: ['#7e9cf6'],
          shadow: true,
          shadowOpacity: 0.2,
          attribution: false
       }
   };
   return settings;
}
var _chart = new RGraph.SVG.Bar(_settings()).draw();			

 

Notice that the chart data is defined by the data property in the settings object.

Say we have a Javascript function that returns an array of values and we want to use the data returned by this function in the Chart. For example, the function that return an array of values could be defined as follows:

function getData() {

    return [1,2,3,4,5,6,7];

}

 

To base the Javascript Chart on the data returned by this function, we simply change the data property in the Chart settings to:

 

....

id: '{chartDiv}',
data: getData(),
options: {....

 

In the case where the data comes from a column in a List control, the Javascript function that gets the data would be something like this (assuming that the column in the List that contains the data is called 'Sales'):

function getData() {

    var lObj = {dialog.object}.getControl('myList');

    var _d = lObj._data //get list data

    var _a = []; //make empty array

    for(var i = 0; i < _d.length; i++) {

        _a.push(_d[i].Sales); //push data from the 'Sales' column onto the array

    };

    return _a;

 

}

 

If the data you want to use in your chart originates server-side, then you will need to create a Data Series. Assume you have created a Data Series called Sales, with two sub-series, Amount and Month.

The data in the Sales Data Series might look something like this:

 

Month Amount
Jan 200
Feb 220
Mar 190
Apr 250
May 270
Jun 210
Jul 300
Aug 320
Sep 290
Oct 330
Nov 300
Dec 350

 

You can reference data from Amount column in the above Data Series using this syntax:

{dialog.object}._dataSeriesData.Sales.Amount

 

Using this syntax, you could change the settings object for the example bar chart to:

 

var _settings = function() { 
   var settings = {
      id: '{chartDiv}',
      data: {dialog.object}._dataSeriesData.Sales.Amount,
      options: {
          gutterTop: 50,
          hmargin: 20,
          xaxisLabels: {dialog.object}._dataSeriesData.Sales.Month,
          tooltips: {dialog.object}._dataSeriesData.Sales.Month,                
          title: 'A basic Bar chart',
          titleSubtitle: 'A chart showing sales by month',
          titleSubtitleItalic: true,                
          colors: ['#7e9cf6'],
          shadow: true,
          shadowOpacity: 0.2,
          attribution: false
       }
   };
   return settings;
}
var _chart = new RGraph.SVG.Bar(_settings()).draw();			

 

Notice that the chart data, X axis labels and tooltips are all based on Data Series data.

 

 

Any Property in the Chart Can Be Dynamic

In the above examples we have set the Chart's data property to the result of a Javascript function call (first example), or to the value in a Data Series (second example). However, it is not just the Chart's data property that can be dynamic. Any property in the Chart settings can be set to a Javascript function, or Data Series value.

For example, in the above example, the Chart Title is defined using this settings:

titleSubtitle: 'A chart showing sales by month'

 

This could be changed to:

titleSubtitle: getChartTitle()

 

 

 

Working in the Javascript Chart Builder

When you are working in the Javascript Chart builder, the dialog has these buttons and hyperlinks.

 

The purpose of each of these buttons or hyperlinks is:

 

 

 

Setting a Chart's Background Color or Border

In some cases, you will want to set the background color or border of a chart. For example, the Chart shown below has a black background.

You can set the Chart background color and border using the Javascript Chart's Style property.

 

 

Setting Javascript Chart Size to 100%

You can set the Javascript Chart width to 100% (useful when the Chart is shown in a Panel Card). However, setting the Chart's height to 100% is not supported. You must specify an explicit height for the Chart. Also, unlike many other UX controls, Javascript Charts do not have a Fill Container property.

NOTE: If you set the Javascript Chart width to 100% and the Javascript Chart is contained inside a Panel Card, the Javascript Chart will automatically be resized when the device orientation is changed.

 

Action Javascript Javascript Chart Actions

The Javascript Chart Action in Action Javascript allows you to:

 

Methods

The following methods are available for working with Javascript charts:

 

{dialog.Object}.jsChartResize(UXJavascriptChart,width,height[,redrawMethod[,methodParameter]])  

Resizes a Javascript chart. You can optionally pass in a draw method to redraw the chart without animation, or with a specified animation option.

Where:



{dialog.Object}.jsChartSetProperties(UXJavascriptChart, properties [,drawMethod [,methodParameters]])

Resizes a Javascript chart. You can optionally pass in a draw method to redraw the chart without animation, or with a specified animation option.

Where:

 

 


{dialog.Object}.jsChartRefreshData(UXJavascriptChart)

Refreshes the data in Data Series that the Chart uses and then redraws the Chart.  An Ajax callback is made to the server to refresh the Data Series and then the Chart is redrawn using the new data. If the Chart is not based on any Data Series, then no Ajax callback is necessary and the Chart is redrawn.

Where:
 

 

{dialog.Object}.jsChartRedraw(UXJavascriptChart [,drawMethod [,drawMethodParameters [,properties]]])

Redraws a Javascript chart. You can optionally pass in a draw method to redraw the chart without animation, or with a specified animation option. You can also
optionally change chart property values when it is redrawn.

Where:

 


Building Dashboard Applications

Javascript Charts are ideal for 'dashboard' applications. You can design a UX component with multiple Javascript Charts each of which displays data on one of the metrics your dashboard is designed to monitor.

In situations where a large number of users are connected to the dashboard, and where you want to update the dashboards frequently, you can use Alpha Anywhere's Web-sockets feature to create an efficient application. Instead of having the UX component make periodic callbacks to the server to refresh the data shown in the dashboard charts, a scheduled CRON job on the server can update data for the dashboard, then when broadcast the data to all of the connected UX components.
 

 

Speed Typing Glossary - Javascript and Xbasic Editors - You can now define abbreviations that get automatically expanded in the Javascript and Xbasic editors. This can significantly improve your productivity when you are writing Xbasic and Javascript code.

For example, say that in the Javascript editor you frequently type the following code:

 

var lObj = {dialog.object}.getControl(

 

You can now define an abbreviation for this code snippet. Every time you type the abbreviation, it is automatically expanded. For example, you might specify that the abbreviation for the above code snippet is .gc.

Every time you type .gc in the code editor, .gc will be replaced with var lObj = {dialog.object}.getControl(.

 

Watch Video

 

The replacement text for the abbreviation can be arbitrarily long. It does not have to be a single line of text as in the above example. You can also specify where the insertion point should be placed after the abbreviation has been expanded.

You can also set rules that control when an abbreviation is expanded. For example, you can specify:

You can also specify if the abbreviations should be shown in auto-complete (just like auto-complete for functions and variables), as shown in the image below. If you specify that an abbreviation should be shown in auto-complete, you can define an optional description that will also be shown in auto-complete.

To define a glossary while editing either Xbasic or Javascript, right click, and select the Edit glossary command from the menu. The glossary editor is shown below:

Each line shows the abbreviation, expansion for the abbreviation, and expansion options ( S - show in auto-complete, F - expand if first word on a line, W - expand if preceded by a word boundary)

 

To edit an individual glossary entry, double click on the item, or click the Edit button. The editor is displayed where you can define both the abbreviation and the replacement text. You can also set the options for the glossary item.

 

 

 

email_send_noprofile() Function - Now allows for a blank username or password. The third parameter for email_send_noprofile() is the security mode. The valid options are blank (""), SSL, and TLS. This parameter is now optional.

 

Flying Start Genie - Row Expanders - The Flying Start Genie allows you to quickly build Grid components for all (or selected) tables in a database. Now, the Genie will automatically detect if there is a relationship between the Grids that are created and it will add a Row Expander to each Grid if that Grid has related Grids.

For example, in the image below which shows the Grid that was created for the Customers table in the sample Northwind database you can see that each row in the Grid has a row expander that shows the Orders for the selected customer. Similarly, the Orders grid has a row expander to show the Order Details for the selected Order.

 

 

 

UX Component - SemiCircularNumberDisplay Control - A new control type is available in the UX component. This control allows you to display a numeric value on a semi-circular chart. It is ideal for using in 'dashboard' type applications. You can configure the color of the control so that it changes depending on the value. For example if a numeric value is in the 'safe' zone, you might set the color to green, and if the value was in the 'danger' zone, you might set the control color to red.

Watch Video - Part 1
Watch Video - Part 2

To add a SemiCircularNumberDisplay control to your UX component, select the [More...] control in the Data Controls section of the UX Toolbox. Like other controls in the Data Controls section of the UX toolbox, the SemiCircularNumberDisplay control has both a .SetValue() and .GetValue() method that allows you to set its value and read its values.

 

 

This will display the list of additional control types:

 

After you add the control to the UX you can configure the properties of the control by clicking on the smart field for Control Properties. This will open a dialog where you can set the properties of the controls.

 

 

Properties of note in the builder include:

 

Defining Dynamic Colors

When you set the Color type to Dynamic you can define a series of ranges and the corresponding color for each range. Click the smart field for the Values ranges property (shown when the Color type is Dynamic) to open the builder (as shown in the image below).

The builder allows you to define multiple ranges and for each range, you can specify a color.

 

 

 

 

 

UX Component - RadioButton - CheckBox Controls - Render as ButtonList - Align - When you set either a Radio Button, or CheckBox control to render as a ButtonList, you can not control the alignment (left or right) of the button labels.

Components - Styles - Customize Colors - Pre-defined Palettes - When you select the 'Alpha' style for a component, you can customize the colors used in the style by simply setting the values of SASS variables.

 

 

When you click the smart field for the Customize style colors and fonts property, a dialog is opened, as shown in the image below, where you can set values for each of the SASS variables used in the style.

Now, when you open the Edit Style SASS Variables dialog, a new button appears at the bottom of the dialog that allows you to select a pre-defined palette.

 

 

When you click the Use a Pre-Defined Color Palette button, the Palette Selector window is opened, as shown below.

When you select a palette from the list, the colors are applied to the items in the Edit Style SASS Variables dialog. If you want to use the colors, click OK. If you click Cancel, the colors are not applied.

If you have selected a palette, and you want to go back to the base theme with no palette, select <none> from the list.

 

 

Setting Min and Max Values at Run-time

The following Javascript snippet shows how you can dynamically set the control's min and max value at run-time.

 

var max = {dialog.object}.getValue('max');
max = Number(max)
//get a pointer to the control
var obj = {dialog.object}.getControl('semicircularNumber_1');

 

//set the min and max
obj.rgraphSettings.max = 200;

obj.rgraphSettings.min = 40;

 

//redraw the control
obj.redraw();

 

Application Server - Alerts - The Alpha Anywhere Application Server Classic server now has the ability to send administrative alerts by email and SMS. This can be configured on the Logging tab of the settings UI. There is also a Test Alerts button. This will send both a test email and a test SMS, if each are enabled, in order to confirm that the settings entered are working as expected.

NOTE: These comments do not apply to the Alpha Anywhere Application Server for IIS.

For email notifications, all that is required is a recipient email address. There is no email server configuration necessary, as emails will be sent using a special account, AppServerAlerts@alphasoftware.com. Multiple recipients may be specified by separating them with a comma.

For SMS notifications, the customer must have their own Twilio account and provide the appropriate account information in the server's settings, along with the recipient SMS number. This functionality will work with a free Twilio account, but Twilio may impose limits on free accounts. Multiple recipients may be specified by separating them with a comma.

Currently there are 4 different notification levels, detailed below. Each level includes all alerts from levels under it (higher number).

Level 1 - Emergency

(Indicates something that requires immediate attention, as the server is no longer operating normally)

Level 2 - Alert

(Indicates something that needs attention very soon, as server functionality will be impacted)


Level 3 - Warning

(Indicates a potential problem)

 

Level 4 - Notice

(Indicates an informational notice)

 

 

Xbasic - a5_ink_to_png() Function - Convert Ink to a PNG Image - The Ink control (in the UX component) uses a special syntax for the Ink data. The a5_ink_to_png() function converts the ink data to a PNG image.

Syntax

a5_ink_to_png(C ink,N heightInPoints,N widthInPoints,C filename)

 

Where:

Javascript Library - A5.runChain() Function - Run Asynchronous Functions Synchronously - A new function has been added to the Alpha Anywhere Javascript library to run asynchronous functions synchronously.

Many Javascript functions run asynchronously. For example, functions that make Ajax callbacks are asynchronous. In PhoneGap applications, most of the functions are asynchronous.
 

This helper function allows you to run a series of functions (some of which may be asynchronous) synchronously (i.e. the second function does not start executing until the first function has completed, and so on).

 

Watch Video - Part 1
Watch Video - Part 2

 

Syntax:

A5.runChain(actions,onAllDone,onStop [, context]);

Where:

Each function in the actions array must take a single object as its input parameter. Each function must call the .next() method of the input object to begin execution of the next function in the actions array. If the function is an asynchronous function, the call to the .next() method would be in the onSuccess callback of the asynchronous function.

The execution chain can be stopped if any function calls the input object's .stop() method.

 

Example

//define 3 functions you want to run asynchronously

 

//this is an asynchronous function

function action1(obj) {

    setTimeout(function() {

        console.log('wait 1 second');

        obj.next() // call the next function to be executed

    },1000 );

   

}

 

function action2(obj) {

    console.log('this is a synchronous function');

 

    obj.next()

}

 

function action3(obj) {

    setTimeout(function() {

        console.log('wait .5 seconds');

        obj.next()

    },500 );

   

}

 

//create an array with the functions to executed

var actions = [action1,action2,action3];

 

//run the actions synchronously

A5.runChain(actions,

    function() { alert('alldone'); },

    function(err) { alert('error: ' + err); }

);

 

//if we want to pass in values to the chain we can do as follows

var context = {var1: 'value of var1'};

A5.runChain(actions,

    function() { alert('alldone'); },

    function(err) { alert('error: ' + err); },

    context

);

 

//inside any of the functions we can reference 'this.var1'

//we can also set properties on the 'this' object.

 

 

 

When you run this code, the messages in the console will appear in the following order:

wait 1 second

this is a synchronous function

wait .5 seconds

 

If you had simply called the functions one after the other, then the messages would have appeared in the following order:

this is a synchronous function

wait .5 seconds

wait 1 second

 

Installing the Alpha Anywhere IDE on Multiple Machines - Deactivating a License - The Alpha Anywhere IDE license allows you to install the  Alpha Anywhere IDE on as many machines as you want, but you can only use it on one machine at a time.

If you have installed the AA IDE on two machines, for example, and you started the AA IDE on one machine and then exited the AA IDE on that machine and tried to start it on the second machine immediately after exiting the AA IDE on the first machine, this would not be possible because the activation 'lease' would not yet have expired. By default, the activation 'lease' for the AA IDE is 24 hours. (This can be changed in the View, Settings, Preferences menu command)

However, if you select the File, Deactivate License and Exit menu command, on the first machine, you would be able to go to the second machine and start the AA IDE immediately. You would not have to wait until the lease on that machine expired.

 

UX Component - List Control - Import Data - If a List control in a UX component is based on data from a SQL database you can now upload an Excel or Ascii file (containing CSV data - comma separated values) and then import the data in that file into the table in the SQL database that the List is based on. After the data are imported, the List is automatically refreshed.

NOTE: If a List is based on a stored procedure, you cannot import data.

The data in the uploaded file must use field names that match the column names in the target SQL table.

In the case of a CSV file, the field names are in the first row of data in the file. In the case of an Excel file, the field names are the column heading in the first row of data.

NOTE: In the case of an Excel file, if the file has multiple tabs, the data on the first tab is imported.

Field names in uploaded file cannot contain spaces, or special characters.

To create an Import Action, use Action Javascript and select the Import Data into a List Control from Excel or Ascii file action.

 

This will open the builder where you can define the define the target List control into which you want to import data.

 

 

The properties of note in the builder include:

Target List control name - The name of the List control into which you want to import data. The data are actually imported into the table in the SQL database that the List is based on. Only Lists that are based on SQL databases (and do not use stored procedures for the List query) are eligible targets.

Pre-process uploaded file Xbasic function - After the file has been uploaded you can call an Xbasic function to validate the data before it is imported into the target table. Your Xbasic function gets passed an array with all of the data to be imported. Your code can modify the data in the array or delete array entries that do not meet validation criteria

Maximum records to process - If the uploaded file contains more records that the specified maximum, no data are imported.

 

Xbasic - Context.Security.AdministrativeCreateUser() Method - Adds a new user with a password.

Normally Context.Security.CreateUser() is used to create users. When the security setting for Reset Password is set require a question and answer, a security question and answer are required to create a user.

This requirement is not practical when an administrative task creates a user.

The AdministrativeCreateUser() method can be used in this case. It does not require a security question and answer even if the security settings require one. Because of this, its use should be limited to pages/code that require administrative access and the application should require the user to set a security question and answer on first login.

 

Web Control Panel - Node Services Category - The Web Control Panel now has a new category - Node Services. This makes it easier to create Node services that can be called from your Xbasic code.

When the Node Services item has focus, the New button will create a new stub Node service that serves as a helpful starting point for defining a new service.

Once you have defined your Node service, you can call it from your Xbasic code using the node_request_result() function.

For example, say you have define a service called multiply and that this service takes as input x and y. Here is how you could call the service from Xbasic:

dim pIn as p

pIn.x = 4

pIn.y = 3

dim pOut as p

pOut = node_request_result("multiply",pIn)

?pOut.error

= ""  'empty string indicates no errors.

?pOut.result

= 12

 

 

Web Control Panel - Node Services Category - The Web Control Panel now has a new category - Node Services - that shows all of the Node services defined in the project.

 

Node_request() Function - Automatic Node Restart -  If you are in WorkingPreview or LivePreview and you have edited the code in a Node Services definition, when you call node_request() to run the service, the optional  flagRestartNode parameter will automatically be set to .T.. This makes iteratively testing edits to a Node service easier to test. Without a Node restart, edits to the Node service definition would not be picked up by Node.

Node_request_result() Function - A wrapper around the node_request() function, except that instead of returning a JSON string, the JSON is already parsed and the function returns a .result and .error property. If there was no error, the .error property is blank.

 

Session Folders - The Alpha Anywhere Application Server now uses A5Storage for session files. A5Storage allows for much greater flexibility in storing session data on local disk, network attached storage, Amazon S3, and Azure. This means that the physical folders previously located in a directory named session_folders within the webroot are no longer used in any way and will not be created by the server.

Direct access to these folders has never been supported by Alpha Software, and the Session.Session_Folder and Session.Session_URL properties were deprecated in version 11 and removed in version 12 (Alpha Anywhere). With this update, ServerSetting.SessionFolders has also been removed.

However, some developers may have written custom code to directly access these folders. Any existing code of this type will no longer function as expected and will need to be updated or replaced accordingly.

See https://www.alphasoftware.com/documentation/pages/Server/Guide/Design/Sessions/Storing%20Files%20in%20Sessions.xml for more information on working with files in Sessions.
 

 

Xbasic - create_table_sql() Function - Excel - You can now pass the name of an Excel file to the create_table_sql() function. This will create a SQL table based on the list of columns in the Excel data and also import the data into the SQL table.

The name of the Excel file is passed in as the fieldList parameter.

 

Xbasic - sql_import() Function - Excel - You can now pass the name of an Excel file to the sql_import() function. This will import the data in the Excel file into the SQL table.

The name of the Excel file is passed in as the data parameter.

 

SQL Server Reporting Services - Using Reports Created in SQL Server Reporting Services in an Alpha Anywhere Project - Many organizations use SQL Server Reporting Services (SSRS) and have a number of reports that were developed in SSRS. Using these reports in an Alpha Anywhere application is now possible using the SSRS integration features in Alpha Anywhere.

 

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

 

In order to use SSRS reports in an Alpha Anywhere project you must:

These steps are discussed in more detail below.

Once you have created a link to a SSRS report, the report link can be used just like any other Alpha Anywhere report. You can add the report to the TabbedUI, or you can create actions using Action Javascript to display the report.

Creating a SSRS Connection String

To create SSRS connection string, select the Tools menu when the Web Control Panel has focus and then select the SQL Server Reporting Services Connection strings menu item.

 

 

You can then define a new connection string, or edit an existing connection string:

 

 

Linking SSRS Reports

To link SSRS reports in your Web Project, go to the Web Projects Control Panel and select the Reports category.

 

 

Then click the New button. The dropdown menu shows these choices:

 

This will bring up a dialog where you can select the SSRS reports you want to link in your Alpha Anywhere project.

Select your SSRS connection string in the Connection String dropdown box. A list of reports defined in the selected SSRS server will be displayed.

NOTE: The first time you connect to a SSRS server, it can take quite a long time before SSRS responds with the list of reports.

Select as many of the listed reports as you want.

Notice that at the bottom of the dialog there is a Preview Reports hyperlink that will allow you to preview any report before you select it. If the selected report uses parameters, you will be prompted for the parameter values.

 

 

Links will be created for each of the selected reports. A link is a file in the Web Projects control panel with information about the SSRS report. The filename includes the .ssrs. string in the name just before the .a5rpt extension.

For example:

 

 

Once a report has been linked, you can set security on the report as if it were a native Alpha Anywhere report. You can add the report to a TabbedUI, or show the report when a button is clicked by using Open a Report action in Action Javascript.

 

Publishing Profiles

When you define a publishing profile to publish your application you can specify values for your SSRS connection strings, just as you can for all other types of connection strings (e.g. AlphaDAO, storage, etc.). This means that you can connect to a different SSRS server when you publish your application than you do when you are developing your application.

 

TabbedUI Component - Search - If a TabbedUI component has a large number of items, it can be difficult for a user to find the item that they want. You can now add a search feature to the TabbedUI to allow users to quickly find the items they are looking form. As the user types into the search box a filtered list of the matching items is displayed (see second image).

Watch Video

 

In the image below the search feature has been turned on, but the user has not yet typed into the search box.

 

 

In this image the user has typed a string into the search box and all of the matching items are displayed.

 

To turn the search feature on, go to the TabbedUI Properties pane in the TabbedUI builder and check the Enable search property.

Once you have turned on the search feature, there are a number of other properties you can set.

 

UX Component - Action Javascript - Get Server-side Data - A new action has been added to Action Javascript. The purpose of the action is to get server-side data and return the data to the client where you can then further process the data with Javascript code. For example, you might use the data returned to populate a List control, a dropdown box, a SpinList etc.

 

The builder for the action is shown below:

 

 

The server-side data can be obtained by performing a query against a SQL database, or by executing a Xbasic function (which can, in turn, call web services - REST or SOAP) to get the data that should be returned to the client.

The options for the Query type parameter are:

 

The onSuccess property allows you to define Javascript to execute once the data is received by the client. The data that is received by the client will be stored in a variable called:

{dialog.object}._serverSideData

 

 

 

UX Component - List Control - Dynamic Images - Image Sequences - Client-side - You can now specify dynamic images when you define a dynamic image field to a List and specify that the dynamic image computation is server side.

Xbasic - SQL_Import() Function - Import data into a SQL Table - The sql_import() function is a helper function that imports CSV or JSON data into a SQL table.

NOTE: The function is called a 'helper' function because it simply wraps the low level AlphaDAO methods for doing a bulk insert into a SQL table.

Syntax

p result = sql_import(c connectionString, c tableName, c tableOwner, c data [, L replicateIdentity [, c fieldMap]])

 

 

Where

Example fieldMap

Assume that the input data is as follows

fname,lname

fred,smith

john,jones

 

Assume that the target table has column names of firstName and lastName.

You would need to specify the following fieldMap:

fname=firstName

lname=lastName

 

Example:

dim cs as c
cs = "mydata"
tablename = "table1"
data = <<%str%
id,name,notes,dob,number
1,"Jones, Amy","Here are some notes",1992-12-18,34.56
%str%

'replicateIdentity = .f.
map = "name=fullname"
 

dim p as p
p = sql_import(cs,tablename,"", data,replicateIdentity,map)
 

?p.error

= .f.


 

UX Component - Map Control - Action Javascript - Google Map Methods - Two new actions have been added to the Google Map Methods action

 

Xbasic - what3words() Function - Add support for the what3words service. Allows you to translate an address or location to a what3words address, or a what3words address to a location. For more information on what3words go to www.what3words.com.

Syntax

p result = what3words(c key, c mode, c input)

Where

Examples

 

key = "Your api key"

mode = "wordstolocation"

input = "traps.plan.code"

dim p as p

p = what3words(key,mode,input)

?p.lat
= 42.423661
?p.lng
= -71.213213

 

mode = "addresstowords"
input = "70 blanchard road, burlington ma usa"

dim p as p
p = what3words(key,mode,input)
?p.words
= "newly.slams.roses"
 

 

 

Xbasic - create_table_sql() Function - Create a table in a SQL database.

 

Syntax

P result = create_table_sql(c fieldList,c connectionString,c tableName [, c mode])

 

Where

 

The fieldList parameter can be either a JSON array of objects defining each field, or a crlf delimited list of pipe delimited properties.

Example of a CRLF delimited fieldList:

 

id|N|6|0|AutoIncrement

name|c|20

dob|d

notes|m

 

In this example a primary key (that is not an AutoIncrement fields) is defined

id|c|6||PrimaryKey

name|c|20

dob|d

notes|m

 

When defining a primary key you can designate multiple columns:

firstname|c|20||PrimaryKey

lastname|c|20||PrimaryKey

dob|d

notes|m

 

 

 

Example of a JSON fieldList:

 

[

    {"name": "id", "type": "numeric", "size": 6, "decimals" : 0, "autoIncrement": true},

    {"name": "name", "type": "character", "size": 20},

    {"name": "dob", "type": "date"},

    {"name": "notes", "type": "memo"}

]

 

In this next example a primary key (that is not an Auto Increment field) is defined:

NOTE: Multiple fields can have the 'primaryKey' attribute set to true.

 

[

    {"name": "id", "type": "character", "size": 6,  "primaryKey": true},

    {"name": "name", "type": "character", "size": 20},

    {"name": "dob", "type": "date"},

    {"name": "notes", "type": "memo"}

]

 

Xbasic - JSON_shred() Function - Converts a complex JSON string representing an array of objects with nested arrays) into individual arrays that do not have any nested arrays.

Syntax:

c result = JSON_shred( c JSON, c schema [, c ParentArrayName])

where

 

Consider the following JSON string:

[
	{"Firstname": "John", "Lastname" : "Smith", "City" : "Boston", "State" : "MA", "Children": [
		{"Name" : "Callie", "Age" : 5},
		{"Name" : "Griffin", "Age" :3},
		{"Name" : "Luke", "Age" : 1}
		]
	}, 
	{"Firstname": "Henry", "Lastname" : "Rhodes", "City" : "New York", "State" : "NY", "Children": [
		{"Name" : "Howard", "Age" : 15},
		{"Name" : "Robert", "Age" : 11}
		]
	}
]
			
			

The JSON is an array in which each object in the array has a nested array of 'children'.

This JSON can be 'shredded' to produce this result:

			
{
    "__top": [
        {
            "Firstname": "John",
            "Lastname": "Smith",
            "City": "Boston",
            "State": "MA"
        },
        {
            "Firstname": "Henry",
            "Lastname": "Rhodes",
            "City": "New York",
            "State": "NY"
        }
    ],
    "Children": [
        {
            "Name": "Callie",
            "Age": 5
        },
        {
            "Name": "Griffin",
            "Age": 3
        },
        {
            "Name": "Luke",
            "Age": 1
        },
        {
            "Name": "Howard",
            "Age": 15
        },
        {
            "Name": "Robert",
            "Age": 11
        }
    ]
}

 

The result is an object with two arrays: __top and Children. Notice however, that since the 'Children' array is no longer nested inside each object in the top level array, the linkage between the entries in the 'Children' array and their parent has been lost.

In the above example, the JSON_shred() function was called using a schema that did not specify that any key fields should be added to the Children array.

The schema used to produce the above result was:

	
[
    {
        "Children" : [
            {
            }
        ]
    }
]

Notice how the  schema defines the 'shape' of the input JSON but does not specify that any additional 'key' fields should be added to the Children array.

In order not to loose the relationship between each object in the Children array to its parent, a key field must be added to each object in the Children array that points to its parent record. The desired output from the shredding operation is shown below:

	
{
    "__top": [
        {
            "Firstname": "John",
            "Lastname": "Smith",
            "City": "Boston",
            "State": "MA"
        },
        {
            "Firstname": "Henry",
            "Lastname": "Rhodes",
            "City": "New York",
            "State": "NY"
        }
    ],
    "Children": [
        {
            "key": "John Smith",
            "Name": "Callie",
            "Age": 5
        },
        {
            "key": "John Smith",
            "Name": "Griffin",
            "Age": 3
        },
        {
            "key": "John Smith",
            "Name": "Luke",
            "Age": 1
        },
        {
            "key": "Henry Rhodes",
            "Name": "Howard",
            "Age": 15
        },
        {
            "key": "Henry Rhodes",
            "Name": "Robert",
            "Age": 11
        }
    ]
}

 

Notice that each record in the 'Children' array now has a property called 'key' that points to its parent record. To obtain the above result, the following schema is used:

	
[
    {
        "Children" : [
            {
            	"key": "{../Firstname} {../LastName}"
            }
        ]
    }
]

 

The schema specifies that each object in the 'Children' array should have a property called 'key' whose value is the "Firstname' and "Lastname" property in the immediate parent object. The syntax used to specify a value from a parent object is ../.  You can reference properties at the grand parent level using ../../, and so on.

 

Here is a more complex example that shows multiple levels of nested arrays in the input JSON. Notice that the "Hobbies" array is an array of strings, not an array of objects. This array is converted into an array of objects in the result.

	
[
	{"Firstname": "John", "Lastname" : "Smith", "City" : "Boston", "State" : "MA", "Children": [
		{"Name" : "Callie", "Age" : 5},
		{"Name" : "Griffin", "Age" :3, "Hobbies" : ["Leggo","Star Wars"]},
		{"Name" : "Luke", "Age" : 1}
		]
	}, 
	{"Firstname": "Henry", "Lastname" : "Rhodes", "City" : "New York", "State" : "NY", "Children": [
		{"Name" : "Howard", "Age" : 15},
		{"Name" : "Robert", "Age" : 11, "Hobbies" : ["Soccer"]}
		]
	}
]		

Here is the schema that could be used to shred the above JSON:

	
[
    {
        "Children" : [
            {
            	"Hobbies" : [ 
            		{ 
            			"hobbyKey" : "{../../Firstname} {../../Lastname}|{../Name}" 
            		}
            	],
            	"key": "{../Firstname} {../LastName}"
            }
        ]
    }
]

And here is the resulting output from the shredding operation:

	
{
    "__top": [
        {
            "Firstname": "John",
            "Lastname": "Smith",
            "City": "Boston",
            "State": "MA"
        },
        {
            "Firstname": "Henry",
            "Lastname": "Rhodes",
            "City": "New York",
            "State": "NY"
        }
    ],
    "Children": [
        {
            "key": "John Smith",
            "Name": "Callie",
            "Age": 5
        },
        {
            "key": "John Smith",
            "Name": "Griffin",
            "Age": 3
        },
        {
            "key": "John Smith",
            "Name": "Luke",
            "Age": 1
        },
        {
            "key": "Henry Rhodes",
            "Name": "Howard",
            "Age": 15
        },
        {
            "key": "Henry Rhodes",
            "Name": "Robert",
            "Age": 11
        }
    ],
    "Hobbies": [
        {
            "hobbyKey": "John Smith|Griffin",
            "__value": "Leggo"
        },
        {
            "hobbyKey": "John Smith|Griffin",
            "__value": "Star Wars"
        },
        {
            "hobbyKey": "Henry Rhodes|Robert",
            "__value": "Soccer"
        }
    ]
}

 

 

PhoneGap App Builder - PhoneGap CLI Build Option - A new option has been added to the PhoneGap App Builder that allows the developer to select and use either PhoneGap Build or a local install of the Cordova CLI (Command Line Interface) to build a PhoneGap App.

Android builds are supported on PC's running Windows and iOS builds are supported on a Mac with Xcode. Using the CLI allows the developer to use the platform's native development tools to build and debug Cordova apps. This also allows the use of plugins that PhoneGap Build does not support because PhoneGap Build does not support the use of plugin hooks.



For the full documentation on the PhoneGap/Cordova CLI Builder, see PhoneGap/Cordova CLI Builder

For a video overview on using the PhoneGap/Cordova CLI Builder, see PhoneGap/Cordova CLI Builder Video Overview

Xbasic - CURL Object - Auto-complete - When you define a CURL object in Xbasic, you now have auto-complete for all of the options available to the .SetOpt() method.

For example:

 

dim c as extension::curl

c.setOpt(

 

As soon as you type the opening (, the bubble help instructs you to right click on the argument value (as shown in the image below) to get a list of the options for the .setOpt() method.

 

 

 

UX Component - FormView Control - Lookup Fields - You can now define lookup fields in the FormView. This allows you to display 'friendly' values in the Form (e.g. product name, rather than product id).

To define a Lookup field, go to the Fields tab in the FormView builder and check the Has Lookup value property.

You can then define the Lookup. The lookup data source can be a List control or a Javascript function.

 

 

 

TIP: You may want to use the client-side data cache or a query against a SQLite database (in a PhoneGap application) as the data source for your Lookup. This requires a two-step process because reading data from the client-side data cache, or from a SQLite database can only be done asynchronously. Therefore you must first execute some code that reads the client-side data cache or executes a SQLite query and puts the data in a variable in memory. You can then define the Lookup in the FormView builder to use the Javascript Function option, performing the lookup against the data you have loaded into memory.

 

Web Project Control Panel - Automatic Refresh - By default every time the list of files in your Web Project changes, or a file is edited, the Web Project Control Panel will refresh. However, if your project contains a very large number of files  (several thousand), then refreshing the Control Panel can be slow and you might want to turn off the automatic refresh of the Control Panel and only refresh it when needed.

You can turn off automatic refresh by clicking on the More... button in the Web Control Panel and selecting the Set Control Panel refresh options... menu entry.

 

 

 

If you turn off automatic refresh, a Refresh button will be shown in the Web Control Panel. Click this button to refresh the Control Panel.

 

 

UX Component - List Controls - Dynamic Images - Image Sequence - When you add a server-side dynamic image to a List control, you can now specify that you want to use an image sequence for the image.

 

 

 

UX Component - Map Control - Adding Multiple Markers to a Map Control Using Client-side Data - Action Javascript has an action to add multiple markers to a map. The data that defines the latitude/longitude for each marker on the map (and also for the marker titles, details etc). has previously been server-side data. Now, you can specify that the data should be client-side data.

In the case of server-side data you specify the name of a Data Series that specifies the properties for each marker. In the case of client-side data, the data can come from a Javascript function, a List control, the client-side Data Cache, or, in the case of a PhoneGap application, by querying a SQLite database on a device.

 

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4
Watch Video - Part 5

Download Component

 

To specify that the Google Map Method (UX Component) / Add multiple markers to the map action should use client-side data, set the Data type property to ClientSideData. You can then specify whether the client-side data comes from a Javascript function, or from data in a List control.

In the case where you specify the name of a Javascript function, you specify the name of a Javascript function (which must return an array of objects - each object has properties that must include the marker latitude and longitude values). You must also specify the names of the properties in the data returned by the Javascript function.

 

 

 

 

For example, assume that you specify the name of a Javascript function that returns data like this:

			
[
		{
			"name": "COYOTE FLATS",
			"city": "BISHOP",
			"state": "CA",
			"latitude": "37.20203",
			"longitude": "-118.47629"
		},
		{
			"name": "LOST HILLS SHERIFF\\'S STATION",
			"city": "CALABASAS",
			"state": "CA",
			"latitude": "34.14167",
			"longitude": "-118.5262"
		},
		{
			"name": "GOLDSTONE /GTS/",
			"city": "BARSTOW",
			"state": "CA",
			"latitude": "35.35053",
			"longitude": "-116.88837"
		}
]
			
			

In this case the property names that you specify in the Javascript properties property would be:

name,city,state,latitude,longitude

 

NOTE: If you want to use data from the client-side Data Cache, or (in the case of a PhoneGap application) data from a query against a SQLite database, you need to use a two-step process because reading data from a Data Cache (or a SQLite database) is an asynchronous action. Therefore your Javascript must read the Data Cache, or execute the SQLite query (you can use Action Javascript for this) and in the on success function for the action, you must put the data you have just read into a variable in the UX object (for example {dialog.object}._mapData) and then call the Action Javascript action to add the markers to a map using the Javascript function option. The Javascript function will read the data from the variable that contains the data.

 

Xbasic - Classes - The Web Control Panel now exposes a new category - Xbasic Class - that allows you to defined Xbasic classes that can then be used in any server-side Xbasic code.

 

To use an Xbasic class in your Xbasic code you use the loadClass() function to load the definition and then you can DIM and instance of the class.

For example:

dim flag as l
flag = loadClass("helloclass")
dim h as helloclass

 

 

NOTE: It is not strictly necessary to use the loadClass() function to load the class before DIMming and instance of the class. If the DIM statement fails, Xbasic will then try to load the class itself by searching for the class definition. But this will add a short delay to your code while Xbasic tries to resolve the class. Therefore it is recommended that you explicitly load the class before using it. Also, if you make an edit to the class definition, the edit will be seen immediately if you explicitly load the class.

 

 

Xbasic - loadClass() Function - Loads a class definition.

Syntax

L flag = loadClass(c className)

Where

 

 

 

UX Component - Integrated Login - Server-side onLogin Event - Enhancements have been made to the server-side onLogin event so the following actions in the onLogin event handler are now supported

 

For example:

 

e.arguments[e.arguments.ArgumentNumber("Arg1")].data = "Portugal"

e._set.field1.value = "foo"

e.control.field2 = "bar"
 

Web Components - Manifest Files - Using Source Control - Most web components use a special support file with a _a5wcmp_manifest file extension. When a component is published, the process checks for a manifest file built at the same time as the requested component. The publish process uses this manifest file to determine what other files need to be published to run the component.

Previously, the file name for each 'manifest' file contained a timestamp string to synchronize the file with its parent component. This caused a problem if the component files were stored in a source control system. (See release notes for 'Grid Component - Compiled Files - Using Source Control' for a complete explanation).

The new process stores the linking timestamp internally in the two files, and the manifest filename never changes. It can now be stored in a source control system with its parent component.


This new naming convention is only applied when a component is edited and resaved, or when the manifest files are updated by a bulk process. Existing components with the legacy file naming will still function normally. Some components such as login and navigation components do not use the new process as they do not build a manifest when saved.

 

UX Component - Alignment Container - The Alignment container makes it easy to left, center, or right align a series of controls.

When you select an Alignment container you can set standard set of properties for  container. If you set the alignment to left or right, then you can also set an offset property to control distance of the controls from the left or right edge.

All of the controls in an Alignment Container render on their own line, regardless of whether or not a break follows the control.

If you want multiple controls to be on the same line, you must wrap the controls in a container and then the Alignment container will align the enclosing container.

 

 

 

The image below shows how the above definition renders (but with the alignment set to Center, not Left as shown in the image).

The width of the Alignment container has been set to 100% and the width of the first three textbox controls have been set to 50%, 75% and 33% respectively. As you can see the controls are all horizontally centered  within the container.

The txt4 and txt5 controls both appear on the same line because they are wrapped in  standard container whose width has been set to 2.5inches. The container itself, which has a red border, is horizontally centered.

 

 

 

UX Component - PhoneGap - New Sample Template - PhoneGap - Sound Effects using Native Sounds - A new sample template component has been added that shows how you can add sound effects to your application using the PhoneGap Low Latency Audio plugin. When you create a new UX component you will see the template listed in the list of available samples.

UX Component - FormView Control - List DataSource - {dialog.object}.formViewCommit() Method - Commit Dirty Fields Only - You can now specify that only fields that were edited should be committed to Form's data source. Only applies if the Form's data source is a List control.

Syntax

var flagOnlyCommitDirtyFields = true;

{dialog.object}.formViewCommit('{form.id}',flagOnlyCommitDirtyFields);

 

Xbasic - csv_to_json() - Convert a CSV string to JSON.  Fields must be comma delimited. First row must be fields names. If a field contains a comma, enclose field in quotes. If a field contains quotes, escape quotes using two consecutive quotes


Example

 

dim txt as c
txt = <<%txt%
ticker,name,price:N,change:N,mktcap,chgPct
"AAPL","Apple Inc.",402.215,"-24.025",377.7B,"-24.025 - -5.64%"
"GOOG","Google Inc.",780.37,"-13.00",257.3B,"-13.00 - -1.64%"
%txt%
 

? csv_to_json(txt)
= [
{ "ticker" : "AAPL" , "name" : "Apple Inc." , "price:N" : "402.215" , "change:N" : "-24.025" , "mktcap" : "377.7B" , "chgPct" : "-24.025 - -5.64%"} ,
{ "ticker" : "GOOG" , "name" : "Google Inc." , "price:N" : "780.37" , "change:N" : "-13.00" , "mktcap" : "257.3B" , "chgPct" : "-13.00 - -1.64%"}
]

 

 

 

 

UX Component - onLogin and onLogout Server-side Event - Setting state variables. You can now use the

e._state.varname = varvalue

syntax to set the value of state variables in the server-side onLogin and onLogout event. Keep in mind that if the UX is set to do a full refresh on logout, setting state variables in the onLogut event is meaningless.

 

 

 

 

Action JavaScript - Stripe Checkout - A5.stripe.getEmbeddedStripeResults Function A new function has been added to Stripe Checkout to handle a unique situation that occurs when the Stripe Checkout control is used within an embedded UX component that is reloaded after its was initially loaded The new function may be called in the onStripeCheckoutComplete event.

Example: onStripeCheckoutComplete event handler

 


var e = {};
if ({dialog.object}.getStripeResults) {
    e = {dialog.object}.getStripeResults();
} else {
    e = A5.stripe.getEmbeddedStripeResults();
}


 

Bugs

UX and Grid Component - onChange Event - Fixed a bug introduced in V4.3.2.

PhoneGap App Builder - ImageMagick - UNC Paths - A problem with UNC paths when using ImageMagick to generate icons has been resolved.

UX Component - Stripe - Fixed an issue when setting the currency type to a non US dollar value.

UX Component - Dynamic Images - Fixed a bug introduced in build 4152 when support for image sequences was introduced.

Xbasic - .Net Integration - Fixed an issue when using Xbasic to work with a .Net assembly

Tips

SQL Server Performance Optimization - Indexes - Performance of queries against SQL Server can be affected by string arguments due to an issue with the SQL Server optimizer. 
 
It appears that when a query has a string value argument, the SQL Server optimizer does not always see the type as matching some types of columns (for example CHAR columns with a fixed size). As a result, the optimizer will ignore indexes and hints to use them and resort to a table scan.
 
For example:

 
SELECT AmountDue, AmountPaid, AccountNumber FROM Invoices WHERE AmountDue > 0 and CustomerId = :CustomerId
 


If CustomerId is defined in the database as Char(5), the optimizer may not recognize the :CustomerId argument contains a matching value because the type of the argument is VARCHAR.
 
In such cases, adding a CAST to the argument value causes the optimizer to choose the appropriate index because the types match:


 
SELECT AmountDue, AmountPaid, AccountNumber FROM Invoices WHERE AmountDue > 0 and CustomerId = CAST(:CustomerId AS CHAR(5))
 
 

 

 

 

Alpha Anywhere V4.3.2 - Build 4119-4825 30-Jan-2017

Features

 

Xbasic - SQL_Update() Function - Updates a record in a SQL table. This function is just a wrapper around the Xbasic AlphaDAO commands to execute a SQL update statement, but it convenient to use for simple cases.

NOTE: The record to update is specified by primary key, not by a generalized WHERE clause. This limitation is intentional so a to eliminate the possibility of unintentionally updating multiple records in the database. If you need to update multiple records you will need to write your own Xbasic code.

 

Syntax

    p result = sql_update(A connection,c tablename,c fieldValuePairs,c primaryKey, a primaryKeyValue [, L execute [, P e ]])

 

Where

 

Example:

 


dim cn as sql::Connection

cn.open("::Name::myconnstring")
tablename = "mytable"
fieldsValuePairs = <<%str%
name=fred smith

date of birth=1952/12/18

salary=78000
%str%
 

'You can also specify field values using JSON
fieldsValuePairs = <<%str%
{
    "name" : "fred smith",
    "date of birth" : "1954/11/25",

    "salary" : "78000"
}
%str%

primaryKey = "id"
primarykeyValue = "1"

p = sql_update(cn,tablename,fieldsValuePairs,primaryKey,primaryKeyvalue)
 

 

 

Xbasic - SQL_Insert() Function - Inserts a record in a SQL table. This function is just a wrapper around the Xbasic AlphaDAO commands to execute a SQL insert statement, but it convenient to use for simple cases.

 

Syntax

    p result = sql_insert(A connection,c tablename,c fieldValuePairs [, L execute[, P e ]]])

 

Where

 

 

Example:

 


dim cn as sql::Connection

cn.open("::Name::myconnstring")
tablename = "mytable"
fieldsValuePairs = <<%str%
name=fred smith

date of birth=1952/12/18

salary=78000
%str%
 

'You can also specify field values using JSON
fieldsValuePairs = <<%str%
{
    "name" : "fred smith",
    "date of birth" : "1954/11/25",

    "salary" : "78000"
}
%str%


p = sql_insert(cn,tablename,fieldsValuePairs)

 

?p.lastInsertedIdentity

= 5
 

 

Application Server - OpenSSL - A new version of OpenSSL is now used. The build is OpenSSL 1.0.2k. For details of the fixes in OpenSSL, see:

                https://www.openssl.org/news/cl102.txt

 

UX Component - {dialog.object}.debugInfoToFile() Method - This method is useful when debugging an application and you want to examine some client-side data. While you can typically use Alerts in client side code to examine data, or in some case use console.log() commands (not always possible when the app is running on a mobile device), this method allows you to write client side data to a file on the server.

In cases where you do not have permission to write to server files (e.g. when running under IIS or on the Alpha Cloud), the companion {dialog.object}.debugInfoToS3() method can be used to write to a file on an S3 bucket.

Syntax

{dialog.object}.debugInfoToFile(data,filename[, append [,silent]])

 

Where

UX Component - {dialog.object}.debugInfoToS3() Method - This method is useful when debugging an application. It allows you to write data to a S3 bucket. See {dialog.object}.debugInfoToFile() Method for more information.

Syntax:

{dialog.object}.debugInfoToS3(data,connectionString,objectName [,append [,silent]])

 

Where

UX and Grid Component - DevArts Zoho CRM ODBC Driver - The DevArts ODBC driver for Zoho CRM is now supported.

Xbasic - json_from_xml() Function - Ignore Attributes - In some cases, when you convert XML to JSON, the XML either does not contain attribute tags, or you want to ignore attribute tags when converting the XML to JSON. This will result in cleaner looking JSON. The json_from_xml() function now takes an optional '-A' attribute to ignore attributes.

For example, consider the following input XML:

 

dim xml as c = <<%str%
<qdbapi>
   <ticket>auth_ticket</ticket>
   <apptoken>app_token</apptoken>
   <query>{'11'.CT.'Bob'}AND{'19'.GTE.'5'}</query>
   <clist>6.7.9.11.16</clist>
   <slist>11.6</slist>
   <fmt>structured</fmt>
   <options>num-4.sortorder-D</options>
</qdbapi>
%str%


showvar(json_reformat(json_from_xml(xml,"qdbapi","-A")))

			

The following JSON in produced:

{
     "qdbapi": {
        "ticket": "auth_ticket",
        "apptoken": "app_token",
        "query": "{'11'.CT.'Bob'}AND{'19'.GTE.'5'}",
        "clist": "6.7.9.11.16",
        "slist": "11.6",
        "fmt": "structured",
        "options": "num-4.sortorder-D"
    }
}
			
			


Grid Component - Compiled Files - Using Source Contro
l - Grid components use a special support file with a _a5wcmp_compiled file extension.


When a Grid component is published, the process checks for a compiled file built at the same time as the requested Grid.
The publish process uses this compiled file to construct the published version of the Grid Component used at run time. If the compiled file is missing or out of date, it is reconstructed, which slows the publish process. In a large project this could add a significant amount of time to the publish operation.

Previously, the file name for each 'compiled' file contained a timestamp string to synchronize the file with its parent Grid. This filename changed every time the Grid was resaved. This caused a problem if the Grid component files were stored in a source control system, as explained below.

At publish time, the timestamp in the filename of the _a5wcmp_compiled file was compared with the last edited time of the Grid component file to determine if the _a5wcmp_compiled was up to date. However, if the Grid files in the project had been restored from a source control system, the last edited time on the Grid component filename would be different from their original value and would no longer match the timestamp stored in the local project _a5wcmp_compiled filename. Because the file name for each 'compiled' file changed at every save, it could not be stored in a source control system. As a result, when publishing the application, it would appear that the _a5wcmp_compiled files were out of date and the _a5wcmp_compiled would have to be re-created, thus slowing down the publishing operation.

Now, the _a5wcmp_compiled filename no longer contains a timestamp. Instead, the timestamp is stored as a property in the Grid and it's _a5wcmp_compiled file. The _a5wcmp_compiled filename never changes when the Grid component is edited and the Grid and its linked compiled file can both be stored in a source control system. If both are updated at the same time, they will still match when retrieved from the source control. You do not need to store the _a5wcmp_compiled files in source control if the Grid will not be edited in source control.

This new naming convention is only applied when a grid is edited and resaved, or when the compiled files are updated by a bulk process. Existing grids with the legacy file naming will still function normally.

 

UX Component - Static HTML Page Head Section - When you turn on the Application Cache for a UX component you can now inject custom markup into the head section of the static HTML page using the new Page head section property.

The common use case for customizing the head section is to include markup that specifies the icons to use should the user choose to make a home screen shortcut for the page.

 

 

When you click the smart field to edit the HEAD section, the editor has a hyperlink that will insert sample markup showing how the home screen icons are defined.

In the example below it is assumed that your project has icons called 'apple-icon-57x57.png', etc.

UX Component - List Control - Detail View - afterSynchronize and afterSynchronizeRecord Server-Side Events - Two new server-side events have been added to the List control.

NOTE: Both of these events must be defined for the top-most parent List in the List hierarchy. For example if your UX has a List showing Customers and a child List showing Orders (and if the child List is set to pre-fetch data), then these events must be defined for the Customer List. Defining these events for the Orders List is meaningless.

 

Xbasic - CURL to Xbasic Genie - The CURL to Xbasic genie has been substantially enhanced. You can now automatically generate sample CURL commands by clicking the Example commands... hyperlink in the genie.

 

When you click on the hyperlink a menu of available example commands is shown. You can use this genie to get a template for how the CURL command should be constructed. Then when you convert the generated CURL command to Xbasic, you will have an excellent starting point for fashioning your Xbasic CURL code to perform the task you want.

The list of examples in the menu is extensive, but if you need a specialized CURL command (for example, you need custom headers), select the More... option.

This will open up a generic CURL command builder, as shown in the image below.


Bugs

UX Component - Google Address Suggest - If you had a Google Address Suggest control on a UX and that control was opened in a TabUI, if the tab containing the UX was closed and then the tab was opened a second time, the Address Suggest control did not work.

REGEX Validation - A recent change in the Regex validator in Grid and UX control validation rules (to support international characters in Regex expressions) broke some regex validations that were previously working

UX Component - PhoneGap - Fixed an issue introduced in build 4015 when creating a PhoneGap appllcation.

SQL Trace - Working Preview - If you checked the SQL Trace checkbox in the AlphaDAO Connection String Builder dialog and then executed SQL in Working Preview, the SQL was not shown in the Trace Window.

Video Library - Refresh - The Refresh command on the Video Library did not always update the list of videos shown in the Video Library.

UX and Grid Component Components - onChange Events - Fixed a bug introduced in build 4095 for Grid and UX controls with onChange event handlers, if the Javascript code had any single quote characters.

Report Preview - E-mail Report - PDF - If you clicked the 'Email Report' button on the Report Preview window to send a report as a PDF, an error was generated.

 

Alpha Anywhere V4.3.2 - Build 4107-4820 24-Jan-2017

Bugs

UX Component - PhoneGap - Fixed an issue introduced in build 4015 when creating a PhoneGap appllcation.

 

 

Alpha Anywhere V4.3.2 - Build 4105-4819 23-Jan-2017

UX Component - Static HTML Page Head Section - When you turn on the Application Cache for a UX component you can now inject custom markup into the head section of the static HTML page using the new Page head section property.

The common use case for customizing the head section is to include markup that specifies the icons to use should the user choose to make a home screen shortcut for the page.

 

 

When you click the smart field to edit the HEAD section, the editor has a hyperlink that will insert sample markup showing how the home screen icons are defined.

In the example below it is assumed that your project has icons called 'apple-icon-57x57.png', etc.

UX Component - List Control - Detail View - afterSynchronize and afterSynchronizeRecord Server-Side Events - Two new server-side events have been added to the List control.

NOTE: Both of these events must be defined for the top-most parent List in the List hierarchy. For example if your UX has a List showing Customers and a child List showing Orders (and if the child List is set to pre-fetch data), then these events must be defined for the Customer List. Defining these events for the Orders List is meaningless.

 

 

Xbasic - CURL to Xbasic Genie - The CURL to Xbasic genie has been substantially enhanced. You can now automatically generate sample CURL commands by clicking the Example commands... hyperlink in the genie.

 

When you click on the hyperlink a menu of available example commands is shown. You can use this genie to get a template for how the CURL command should be constructed. Then when you convert the generated CURL command to Xbasic, you will have an excellent starting point for fashioning your Xbasic CURL code to perform the task you want.

The list of examples in the menu is extensive, but if you need a specialized CURL command (for example, you need custom headers), select the More... option.

This will open up a generic CURL command builder, as shown in the image below.


Bugs

 

SQL Trace - Working Preview - If you checked the SQL Trace checkbox in the AlphaDAO Connection String Builder dialog and then executed SQL in Working Preview, the SQL was not shown in the Trace Window.

Video Library - Refresh - The Refresh command on the Video Library did not always update the list of videos shown in the Video Library.

UX and Grid Component Components - onChange Events - Fixed a bug introduced in build 4095 for Grid and UX controls with onChange event handlers, if the Javascript code had any single quote characters.

Report Preview - E-mail Report - PDF - If you clicked the 'Email Report' button on the Report Preview window to send a report as a PDF, an error was generated.

 

 

Alpha Anywhere V4.3.2 - Build 4099-4819 20-Jan-2017

Bugs

UX and Grid Component Components - onChange Events - Fixed a bug introduced in build 4095 for Grid and UX controls with onChange event handlers, if the Javascript code had any single quote characters.

Report Preview - E-mail Report - PDF - If you clicked the 'Email Report' button on the Report Preview window to send a report as a PDF, an error was generated.

 

Alpha Anywhere V4.3.2 - Build 4095-4816 18-Jan-2017

Bugs

Grid Component - Query By Example - If you added two or more filter conditions, ran the query, then removed one of the two filter conditions and then added a third condition, you would get an error.

UX Component - onChange Event - Pre-render - If a UX component had an event handler for the onChange event for a control then if the component was set to pre-render and if the component was shown though an Ajax callback and if the event handler used single quotes in the Javascript, you would get an error.

 

Alpha Anywhere V4.3.2 - Build 4089-4815 15-Jan-2017

Bugs

UX Component - List Control - Detail View - Multi-Column Primary Key - Fixed an issue when adding a new record to a List that was based on a SQL table with a multi-column primary key. This issue was introduced in Version 4.3.2

UX Component - DropDownBox, RadioButton and CheckBox Controls - Choices - Connection String - The connection string builder did not open because of a recent bug that had been introduced.

Reports - Conditional Objects - Fixes to the Conditional Object in reports that resulted from a recent change to this control.

Alpha Anywhere V4.3.2 - Build 4081-4811 11-Jan-2017

Features

Xbasic - AlphaDAO - Date and Number Formats - The SQL::Connection object now supports three new properties that allow you to control the format for date and number fields when the .toJSON() or .toJSONObjectSyntax() methods are called.

 

 

By default, if these properties are not set, the the date format and the decimal separator are inherited from the machine's regional settings

 

 Note:  The properties must be set on the connection BEFORE the result set is created.

 

 

Example Usage


 
dim cn as sql::connection

?cn.open("::Name::Access_Northwind")
= .T.
cn.PortableSQLEnabled = .t.
cn.JSONDateFormat                                       = "yyyy-MM-dd"

cn.JSONDateTimeFormat                             = "yyyy-MM-dd hh:mm::ss 3"

cn.JSONDecimalSeparator                           = ","

?cn.tojson("select first 5 orderdate, freight from orders")

= [
{"orderdate" : "1996-07-04 00:00::00 000", "freight" : "32,38"},

{"orderdate" : "1996-07-05 00:00::00 000", "freight" : "11,61"},

{"orderdate" : "1996-07-08 00:00::00 000", "freight" : "65,83"},

{"orderdate" : "1996-07-08 00:00::00 000", "freight" : "41,34"},

{"orderdate" : "1996-07-10 00:00::00 000", "freight" : "58,17"}

]

 


 

Bugs

Reports - Conditional Objects - A bug was introduced recently that broke reports with conditional objects.

UX Component - List Control - Dates - A bug was introduced in the last update where, if the client-side data format did not match the server-side data format, dates with days less than 13 (e.g. 13 Oct 2017) were not being persisted to the database correctly

Alpha Anywhere V4.3.2  - Build 4077-4809  09-Jan-2017

Videos

UX Component - Ink Control Image Annotation using the Ink Control in a Data Bound UX Component The ink control allows you to create sketches by 'drawing' with your mouse, any type of pointing device, or with your finger (on a device that supports touch). A common use of the ink control is to annotate images. The image you want to annotate is shown as the background to the ink control and then you can draw 'on top of' the image. When the data are saved the ink is stored separately from the image in a long text field.

In this video we show how a data bound UX component that allows a user to upload images can be configured to allow the user to annotate the images that are uploaded.


Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4

Download Component
Download SQL Table Definition

Date added: 2016-10-30
UX Component - ControlBar Control Defining Disclosure Forms using the Disclosure Form Builder In the video 'Displaying a Modal Pop-up Form using a Disclosure' we show how a modal pop-up form can be displayed using a Disclosure. The definition of the HTML for the form is fairly tedious because it is completely hand coded.

In this video we show how the Disclosure Form Builder can be used to make it easier to define the form HTML.


Watch Video - Part 1
Watch Video - Part 2

Download Component

Date added: 2016-10-30
UX Component ControlBar Control Display Modal Message Dialogs using Disclosures Modal messages (such as confirmations, progress, feedback) as commonly used when designing the user interface for an application. ControlBar disclosures make displaying these messages particularly easy.

In this video we show how the ControlBar can be configured to display three different types of message dialogs: basic information dialogs (one button), confirmation dialogs (two buttons) and wait dialogs (no buttons).

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Download Component

Date added: 2016-10-30
UX Component - List Control Specifying Sort Criteria when Filtering a List Action Javascript allows you to easily define fields on a UX where the user can specify search criteria for a List control on the UX ( much like the Search Part in a Grid). Now you can also define sort criteria.

In this video we show how the Filter Records in a List action in Action Javascript can be configured to allow sort criteria to be specified.

Watch Video

Download Component

Date added: 2016-1-03
UX Component - ControlBar Control Adding List Navigation Buttons to a ControlBar When you define a List control, you can specify that the List should be paginated. If you set the pagination method to 'Navigation Buttons' then you must define buttons to move to the next and previous page of records. In a mobile application that uses a ControlBar in a Panel header or footer, it is desirable to place these navigation buttons in the ControlBar.

In this video we show how you can quickly add List navigation buttons to a ControlBar by selecting the 'Pre-defined buttons' option when adding ControlBar items to your ControlBar definition.

Watch Video

Date added: 2016-11-05
UX Component - FormView Control Using a FormView Control to Edit Data in a List Control - Master-Detail Forms - Very Large Forms By default, when you configure a List with a Detail View (so that edits can be made to the List data), the Detail View is composed using individual controls (e.g. Textbox, Textarea, Dropdown, etc). If the Detail View has a large number of fields, then composing the Detail View using individual controls will be inefficient and will result is a very large UX component that may not perform well.

An alternative approach is to use the FormView control to implement the List's Detail View. This is extremely efficient and will allow you to build UX components that edit very large forms but still perform very well.

In this video we show how a master-detail Form is built using a FormView control to edit the fields in the Master table and a second FormView control to edit the fields in the Detail Table. The master table has 100 fields and the detail table has 100 fields, so in total, the UX component is editing 200 fields.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4

Download Component

Download Script to Create SQL Tables

Date added: 2016-11-08
UX Component - FormView Control Tutorial - Building a Mobile Master-Detail Form using The List, FormView and ControlBar Controls - In this video tutorial we show how a mobile app can be built to implement a master-detail form using the FormView control. The app will allow users to edit data from the Customers and Orders table in the sample Northwind database. This is a classic master-detail form: Each customer has multiple orders. The UX component uses two Lists joined in a parent-child relationship. The parent List displays data from the Customer table and the child List display the related orders from the Orders table.

Each List has a Detail View, but in both cases, the Detail View is implemented using the FormView control.

Once the basic functionality of the app has been built, the app is 'mobilized' by wrapping the various sections of the component in PanelCards and a ControlBar is added to implement navigation between the various parts of the application.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4
Watch Video - Part 5
Watch Video - Part 6
Watch Video - Part 7
Watch Video - Part 8
Watch Video - Part 9
Watch Video - Part 10

Download Components

Date added: 2016-11-10
UX Component Displaying a Custom Wait Message while a Large Mobile App is Loading in the Background If you have built a very large mobile App which takes some time to load, you might want to display a custom wait message to the user while the main UX component of your App is loaded in the background.

In this video we show how this can be done using a simple 'startup' UX component.

Watch Video

Download Components

Date added: 2016-12-11
UX Component - PhoneGap PhoneGap - Using the PhoneGap - Open File with Native Application Action to View PDF Files in a Mobile Application The PhoneGap cordova-open plugin allows you to open various file types using the associated native app on a mobile device. For example, if you open a .pdf file, the PDF file is displayed using the native PDF viewer app on the mobile device. If you open a .mp4 file, the video is displayed using the native video viewer on the device. A common use case for this plugin is to download several files when a connection is available so that the files can then be viewer later on when no connection is available.

In this video we show how an application is built that shows a list of PDF files. These files are downloaded from the server and stored in the filesystem on a mobile device. Then we show how each of the downloaded files can be viewed using the PDF viewer on the mobile device. Because the PDF files are stored in the filesystem on the device, they can be viewed even if the device no longer has a connection. The application uses the 'PhoneGap - Open File with Native Application' action to display the .pdf file.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Date added: 2016-12-27
UX Component - PhoneGap PhoneGap- Viewing Reports in PDF Format on a Mobile Device The PhoneGap cordova-open plugin allows you to open files (such as .pdf files) using the natvie application associated with that file type on a mobile device. This plugin is particularly useful for viewing PDF files. The Alpha Anywhere report writer can save reports as PDF files. The cordova-open plugin therefore fits really well with the Alpha Anywhere report writer because you can build applications that generate reports as PDF files and then display the reports on a mobile device using the cordova-open plugin.

In this video we show how you can use Action Javascript (the  'PhoneGap - Open File with Native Application' action) to generate a PDF file from an Alpha Anywhere report, then download the resulting PDF file to a mobile device and display it using the native PDF viewer.


Watch Video - Part 1
Watch Video - Part 2

Date added: 2016-12-27

Features

 

 

Xbasic - Javascript Web Tokens (JWT) - Additional Options - Additional options have been added to the Xbasic classes for generating Javascript Web Tokens. For more details refer to the documentation.

 

IIS Application Server - PKI Authentication - Support has been added for PKI authentication. For more details refer to the documentation.

Watch Video - Part 1
Watch Video - Part 2
 

Xbasic - Extension::JSON Class - New methods - New methods have been added to the extension::JSON class to make it easier to extract data from a JSON object.

NOTE: You can generally easily extract data from a JSON string by parsing the JSON to an Xbasic dot variable, using the json_parse() method. But if the JSON has property names that are not valid Xbasic variable names, then you cannot parse the JSON. Also, parsing an extremely large JSON string could be slow. The methods described here do not require the JSON to be parsed into an Xbasic dot variable, and work for all types of JSON property names.

 

Methods 1

extension::JSON::OffsetToPath(json,offset[,base])

where:

 

 Returns a 'path' to the JSON element that contains the text at the specified offset.

 

Example:

Assume that json is a variable that contains the sample JSON shown below

?extension::JSON::OffsetToPath(json,540,1)
= "[1].orders[1].orderItems[1]"
 

This means that the path in the JSON to the element that contains the text at position 540 is:

[1].orders[1].orderItems[1]

 

Method 2

extension::JSON::PathToOffset(json,path[,base])

where:

 

Returns the offset in the JSON string for the element specified by the path.

 

Example:

Assume that json is a variable that contains the sample JSON shown below


?extension::JSON::PathToOffset(json,"[1].orders[1].orderItems[1]",1)
= 355

 

Method 3

extension::JSON::PathExtract(json,path[,base])
 

where:

Extracts a JSON element for a specified path

 

Example:

 

?extension::JSON::PathExtract(json,"[1].orders[1].orderItems[1]",1)


= {
	"OrderID": "10643",
	"ProductID": "28",
	"Quantity": "15",
	"UnitPrice": "45.6"
}


Sample JSON string for above examples:


		
		[
        {
            "CustomerID": "ALFKI",
            "CompanyName": "Alfreds Futterkiste",
            "orders": [
                {
                    "OrderID": "10643",
                    "CustomerID": "ALFKI",
                    "OrderDate": "09/25/1995 12:00:00 00 am",
                    "orderItems": [
                        {
                            "OrderID": "10643",
                            "ProductID": "28",
                            "Quantity": "15",
                            "UnitPrice": "45.6"
                        },
                        {
                            "OrderID": "10643",
                            "ProductID": "39",
                            "Quantity": "21",
                            "UnitPrice": "18"
                        },
                        {
                            "OrderID": "10643",
                            "ProductID": "46",
                            "Quantity": "2",
                            "UnitPrice": "12"
                        }
                    ]
                },
                {
                    "OrderID": "10692",
                    "CustomerID": "ALFKI",
                    "OrderDate": "11/03/1995 12:00:00 00 am",
                    "orderItems": [
                        {
                            "OrderID": "10692",
                            "ProductID": "63",
                            "Quantity": "20",
                            "UnitPrice": "43.9"
                        }
                    ]
                },
                {
                    "OrderID": "10702",
                    "CustomerID": "ALFKI",
                    "OrderDate": "11/13/1995 12:00:00 00 am",
                    "orderItems": [
                        {
                            "OrderID": "10702",
                            "ProductID": "3",
                            "Quantity": "6",
                            "UnitPrice": "10"
                        },
                        {
                            "OrderID": "10702",
                            "ProductID": "76",
                            "Quantity": "15",
                            "UnitPrice": "18"
                        }
                    ]
                },
                {
                    "OrderID": "10835",
                    "CustomerID": "ALFKI",
                    "OrderDate": "02/15/1996 12:00:00 00 am",
                    "orderItems": [
                        {
                            "OrderID": "10835",
                            "ProductID": "59",
                            "Quantity": "15",
                            "UnitPrice": "55"
                        },
                        {
                            "OrderID": "10835",
                            "ProductID": "77",
                            "Quantity": "2",
                            "UnitPrice": "13"
                        }
                    ]
                },
                {
                    "OrderID": "10952",
                    "CustomerID": "ALFKI",
                    "OrderDate": "04/15/1996 12:00:00 00 am",
                    "orderItems": [
                        {
                            "OrderID": "10952",
                            "ProductID": "6",
                            "Quantity": "16",
                            "UnitPrice": "25"
                        },
                        {
                            "OrderID": "10952",
                            "ProductID": "28",
                            "Quantity": "2",
                            "UnitPrice": "45.6"
                        }
                    ]
                },
                {
                    "OrderID": "11011",
                    "CustomerID": "ALFKI",
                    "OrderDate": "05/09/1996 12:00:00 00 am",
                    "orderItems": [
                        {
                            "OrderID": "11011",
                            "ProductID": "58",
                            "Quantity": "40",
                            "UnitPrice": "13.25"
                        },
                        {
                            "OrderID": "11011",
                            "ProductID": "71",
                            "Quantity": "20",
                            "UnitPrice": "21.5"
                        }
                    ]
                }
            ]
        }
    ]


		
		

Sample Xbasic script that shows an Xdialog to show how these methods can be used:

 
'sample.json contains some sample json data						
dim json as c = file.to_string("C:\data\sample.json")

dim def.text as c = json
dim def.object as p
dim selection as c
dim subselect as c
ui_dlg_box("JSON",<<%dlg%
{watch=def.object.get_selection_start(.t.)!cursor}
[%M;K%.100,20def];
Path;
[.100path] <copy<;
[.100selection] <select>;
[%M;K%.100,5subselect];
%dlg%,<<%code%
if a_dlg_button = "cursor" then
	a_dlg_button = ""
	dim pos as n = def.object.get_selection_start(.t.)
	path = extension::JSON::OffsetToPath(strtran(def.text,crlf()," "),pos)
else if a_dlg_button = "copy" then
	a_dlg_button = ""
	selection = path
else if a_dlg_button = "select" then
	a_dlg_button = ""
	dim pos as n = extension::JSON::PathToOffset(strtran(def.text,crlf()," "),selection)
	if pos < 1 then		
		dim subselect as c = extension::JSON::PathExtract( strtran(def.text,crlf()," "),selection)
		def.object.select(pos,len(subselect) )
		def.object.show_caret()
	else
	   ui_msg_box("","Not found")	
	end if	
end if
%code%)						
					

UX Component - Client-Side Properties - On Get Value and On Set Value - Two new client-side properties have been added for Data Controls in a UX component.

 

 

In both cases, your Javascript can reference a variable called value and must return a value. For example, in the following example, the .getValue() method will return the upper case version of the control's value

 

return value.toUpperCase()

 

These methods can be used to translate a stored value into a display value and vice versa. For example, you might want to display a part description, but store the part number. The data used to to the translation might be stored in a client-side data cache.

 

UX Component - PhoneGap - Cordova-Open Plugin - The PhoneGap genie now exposes the Cordova-Open plugin. This plugin allows you to open files using their associated native application. For example, if you open a file with a .pdf extension the plugin will open the file using the native PDF application on the device. If you open a file with a .mov extension, the plugin will open the file using the native video player on the device.

The Cordova Open plugin is selected in the PhoneGap genie as shown in the image below.

 

 

There are many use cases for the Cordova-Open plugin, but PDF files is perhaps the most compelling use case. Displaying PDF files in a mobile application can be tricky because the browsers on mobile devices do not have built-in PDF viewers as is typical with desktop browsers.

Another great use case for this plugin is a mobile app that downloads multiple files (pdf, video, audio, excel, word, etc.) and then stores these files in the filesystem on the device so that they can be viewer later when the device is no longer connected to the internet. For more information on techniques for downloading files to a mobile device, see this topic in the Tips section: Downloading Files to a Mobile Device.

A new action in Action Javascript (PhoneGap - Open File with Native Application) makes it easy to use the Cordova-Open plugin in mobile applications.

The image below shows how a PDF file appears in the Native PDF viewer on an iPhone (in this case the PDF file was created by generating a report and saving the report output to a PDF file). Notice the Done button that will return you to the app when you close the Native Viewer.

 

 

UX Component - Action Javascript - PhoneGap - Open File with Native Application Action - This action allows you to open a file on a mobile device using the associated native application.

 

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

 

NOTE: You can only use this action in a PhoneGap application. The PhoneGap application must load the Cordova Open plugin.

The action allows you to:

 

When you select the PhoneGap - Open File with Native Application action in Action Javascript, the following dialog is shown:

 

 

If you specify that the file is remote, you must specify the File URL.

 

 

 

If you specify that you want to make an Ajax callback to get the file to open, you must specify the Ajax callback type

 

 

If you set the Ajax callback type to Report, you must specify which report you want to run.

 

NOTE: Alpha Anywhere will automatically send the following Javascript to the client once the report has been created:
{dialog.object}.hideWaitMessage();
This is useful because if you displayed a wait message when invoking the action to save a report as a PDF file, the wait message will automatically be closed once the report has been generated. You do not have to specify an onComplete Javascript property solely for the purpose of hiding a wait message.

 

Report Definition Genie

When you click the smart field for the Report definition property, the following dialog is shown where you can specify the name of the report to run and other properties of the report, such as the filter, and order, PDF options (such as whether the PDF file should have a watermark, etc.) and argument bindings.

 

The filter you define for the report in this dialog is in addition to any filter defined in the report definition itself.

When defining a filter, it is common to use arguments in the filter rather than literal values. For example:

Country = :whatcoutry

rather than

Country = '{country}'

where {country} is the value in a control called Country on the UX component.

To create an argument to use in a report filter click on the Define Arguments button shown in the above image and then bind the argument to a value (either a static value, or a value in a UX control) in the Set Argument Values section of the dialog.

 

Understanding the onComplete Javascript Property

When you set the Ajax Callback type to Report, the onComplete Javascript property allows you to define the name of a Javascript function that will be called after the report has been generated on the server.

Your function will take a single parameter as its input. This parameter is an object with these properties:

A common use case for this function is to store the name of the report and its associated properties (such as filesystem part, filename, etc), in a List control so that the user can quickly view a previously viewed report by simply viewing the file for that report (which is stored on the device after it is viewed for the first time). This allows the user to view reports even when there is no connection.

For example, the following function would store the report information in a List control called previouslyViewedReports:

 

(Assume that the List control has columns named filename, reportname, fspart and folder).

 

function afterReportGenerated(obj) {
 

    var l = {dialog.object}.getControl('previouslyViewedReports');
    var _d = [

        {

            filename: obj.localFilename,

            reportname: obj.reportName,

            fspart: obj.fileSystem,

            folder: obj.folder

        }

    ];
    l.appendRows(_d);
}

 

 

 

Alpha Anywhere Application Server - Building Connection Strings - If you have a remote server that does not have the Alpha Anywhere development version installed, building an ad-hoc connection string that you can paste into the a5_appllication.a5i file can be difficult.

There is now a hyperlink on the Web Server Settings dialog on the Other tab to Open the Connection String Builder Genie.  This opens the regular connection string builder where a new connection can be built and tested. It will also verify if the correct client driver is installed, as the test connection option will fail if the driver is not correct.  The generated string is shown in a simple dialog with an option to Copy to clipboard when the genie is closed. This allows creating and testing a connection in the same environment where it will be used.


Xdialog - {Condition_else} Directive - The {condition_else} directive makes it much easier to display Xdialogs that have conditional sections that render in the same place. Previously it was necessary to use the {start_pos} directive to get the second and subsequent condition to render in the same space as the first condition.

 

For example:

 

ui_dlg_box("Conditional Sections",<<%dlg%
{removeleadingspaces}
{removecomments}
{region}
    Condition: [condition^=conditions];
    {condition_begin=condition="condition1"}
        {region}
            This is condition 1;
        {endregion}  
    {condition_else=condition="condition2"}
        {region}
            This is condition 2;
        {endregion}  
    {condition_else=condition="condition3"}
        {region}
            This is condition 3;
        {endregion}
    {condition_else}
        {region}
            This is any other condition; 
        {endregion};
    {condition_end};
{endregion};

{line=1,0};
{justify=right}<Close>
%dlg%)

 

The images below show how the Xidialog renders for various conditions. Note that when 'condition4' is selected, the {condition_else} text is show because there is no handler for this condition.
 

 

 

Xbasic - Sys_shell_wait() Function -   SYS_SHELL_WAIT() now has two additional parameters (in addition to the command and the ShowWindow flag):

 Note: SYS_SHELL_WAIT() does not throw any errors if something fails.


 
There is a new function called Run() that accepts all of the same parameters (in fact is now called by sys_shell_wait() ) but will return an error if something doesn't work.

Example Interactive Window Session


Run("CMD.EXE /C \"DIR C:\*.* /s\"", .t.,1000,.t.)
ERROR: Application timed out.
 
SYS_SHELL_WAIT("CMD.EXE /C \"DIR C:\*.* /s\"", .t.,1000,.t.)
 

 

UX Components - List and ViewBox Controls - SQL Data Sources - Security and Server-side Show Hide Expressions - You can now apply security settings and server-side show/hide expressions to individual columns in the SQL queries that are used to populate List and ViewBox controls.

 

To define security and/or server-side show/hide expressions for individual columns in a SQL query, click on the smart field for the Security and Show/hide Expressions property (as shown in the image below)

 

 

This will open a builder where you can define settings for each column in the SQL query.

 

 

At run-time, before the SQL is executed, if any of the columns in the SQL SELECT statement have security or show/hide expressions, the columns that should not be shown are removed from the SQL SELECT statement. This means that if a user is not authorized to see a particular column in a SQL query, the data that are sent to the client does not include the excluded columns.

Contrast this with applying security or show/hide expressions to individual fields in the List (in the 'Fields' pane of the List builder). When you apply security to List fields that merely removes a hidden column from the List display. But the data for the hidden column is still set to the client and would be visible if the user viewed the source of the page.

NOTE: You can only apply security and show/hide settings to the SQL if Alpha Anywhere can parse the SQL statement. For example, if the data source for a List is a stored procedure, then, since this is not a parse-able statement, you cannot apply security and show/hide settings.

 

UX Component - Step Indicator Control - The Step Indicator control is used to show what step a user is on in a multi-step action.

The image below shows a Step Indicator control configured to show four steps, labeled One, Two, Three and Four

 

When you add a Step Indicator control you can specify as many steps as you want and you can define the labels for each step. You can also control the color of the completed steps (blue in the above example) and the un-completed steps (gray in the above example).

The Step Indicator control is a Data Control. This means that you can set its value using the {dialog.object}.setValue() method and you can read its value using the {dialog.object}.getValue() method.

For example, to set the above control so that it shows you are at the beginning of the sequence (on the first step) you would use:

{dialog.object}.setValue('name of control',0)

To set the control's value so that it shows you are on step Three (i.e. as shown in the above image) you would use:

{dialog.object}.setValue('name of control',2)

 

To add a new Step Indicator control to a UX, select the [More...] entry in the UX toolbox in the Data Controls section.

 

 

This display a list of additional control types.

 

To configure a Step Indicator control, click the smart field for the control's Control Properties property.

 

 

In the image below, the 'Dot' size has been increased, the 'Show step indicators as circles' property has been turned off and the 'Dot size' has been set to '40px'. A small border radius of 2px has been set so that the 'dot' (squares in this case) have slightly rounded edges.

 

 

Xbasic - a5Helper_SQL_ApplySecurity() Function - The a5Helper_SQL_ApplySecurity() function applies security and server-side show/hide expressions to a SQL SELECT Statement. Any column that is not authorized by the security group or server-side show/hide expression is removed from the SQL Select statement.

The SQL statement you pass to this function must be parseable. If Alpha Anywhere cannot parse the statement (e.g. the SQL is a call to a stored procedure), the function returns the original SQL statement.

If a column does not have a security setting or server-side show/hide expression is will be included in the SQL statement.

If a column has a defined security setting that the column will only be included in the SQL statement if the logged in user is a member of one of the security groups specified by the column's security setting.

If a column as a show/hide expression the column will only be included in the SQL statement if the expression evaluates to a true result.

Syntax

c SQLStatement = a5Helper_SQL_ApplySecurity(sql as c , securityDef as c , loggedInGroups as c)

Where:

 

securityDef is a JSON array of objects. Each object in the array has these properties

 

 

The column specify in the securityDef must match exactly how the SQL parser represents the column. For example, consider the following column expression

concatenate(customers.name , ', ', customers.contacttitle)

 

The meaning of this expression is unchanged if the expression is written as:

concatenate(     customers.name     , ', ',     customers.contacttitle   )

 

However, this is not how the expression is represented in the SQL parser. To get the correct representation of the expression, you can use the code below:

dim si as sql::Query::SelectItem
sql2 = "concatenate(   customers.name   , ', ',   customers.contacttitle)"
?si.Parse(sql2)
= .T.

?si.SQLStatement
= "concatenate(customers.name, ', ', customers.contacttitle)"
 

 

Example

sql = <<%str%
SELECT customers.CustomerID as cid, customers.CompanyName as compName, customers.ContactName, customers.ContactTitle, concatenate(customers.name,', ',customers.contacttitle) as exp1, orders.OrderID, orders.CustomerID AS CustomerID1, orders.EmployeeID, orders.OrderDate, orders.RequiredDate
FROM customers customers
 INNER JOIN orders orders
 ON customers.CustomerID = orders.CustomerID
%str%
 

'define the security settings

dim ss[0] as p
ss[].column = "customers.ContactTitle"
ss[..].security = ""
ss[..].showHide = "session.var1 = \"alpha\""
 

ss[].column = "concatenate(customers.name, ', ', customers.contacttitle)"
ss[..].security = "Sales,Marketing"
ss[..].showhide = ""
 

ss[].column = "customers.CompanyName"
ss[..].security = "Administrator"
ss[..].showhide = ""

 

dim security as c

'Generate a JSON string
security = json_generate(ss)

 

dim loggedInGroups as c

loggedInGroups = Context.Security.GetUserRoles()


sql2 = a5Helper_SQL_ApplySecurity(sql,security,loggedInGroups)
 

 

UX Component - PhoneGap Applications - Delay Function Calls Until PhoneGap is Ready - Typically, when a need to execute a method that can only be run after PhoneGap has loaded, you add code to the onPhoneGap ready client-side event. But in some cases this is not practical and you might already have some code that runs in the onRenderComplete, or onPrepareComplete event and some of the methods in these events need to wait till PhoneGap is ready.

The new {dialog.object}._delayTillPhoneGapReady() method allows you to register function calls that will only be made once PhoneGap is ready.

The syntax is:

{dialog.object}._delayTillPhoneGapReady(functionToExecute, scope, arguments)

 

For example, say you wanted to call the List Object's ._fetchMediaFiles() method.

Normally your code would be

var lObj = {dialog.object}.getControl('LISTNAME');

lObj._fetchMediaFiles()

 

This could be rewritten as

var lObj = {dialog.object}.getControl('LISTNAME');

{dialog.object}._delayTillPhoneGapReady(_fetchMediaFiles,lObj)

 

 

UX Component - Building Component Programmatically Using Xbasic - Absolute Layout Containers - You can now use the a5wcb_createDialogUsingXbasic() Xbasic function to create a UX component that define a component that contains an Absolute Layout container. This is made possible because the Absolute Layout's absolutePositions property now allows you to specify the variablename of the control in the absolute layout, rather than its idInternal property, which cannot be used because it is dynamically assigned when a5wcb_createDialogUsingXbasic() executes.

 

dim wp as p
DIM wp.page_fields[0] as P

with wp.page_fields[]
.controltype = "layout_directive_ContainerBegin"
.v.container.subType = "AbsoluteLayout"
.v.container.id = "ABS1"
.v.container.absolutePositions = <<%str%
[
    {
        variablename: 'c',
        top: '7px',
        left: '16px',
        height: '28px',
        width: '139px',
        style: 'position: absolute; top: 7px; left: 16px; width: 139px; height: 28px; '
    },
    {
        variablename: 'd',
        top: '156px',
        left: '141px',
        height: '27px',
        width: '132px',
        style: 'position: absolute; top: 156px; left: 141px; width: 132px; height: 27px; '
    }
]

%str%
end with

with wp.page_fields[]
    .v.variableName = "c"
    .v.breakType = "None"
end with

with wp.page_fields[]
    .v.variableName = "d"
    .v.label = "Field D"
    .v.hasWaterMark = .t.
    .v.waterMark.text = "Enter name"
end with

with wp.page_fields[]
    .controltype = "layout_directive_Containerend"
end with

a5wcb_createDialogUsingXbasic(wp,"genByXbasic",.t.)
 

PDF Reports - Embed Fonts - In certain cases, PDF reports generated will not render correctly on iOS devices. This is because, by default, the PDFs are generated with the 'Embed fonts' option set to false. The PDFs do not render on the iOS devices because they use fonts they are not native to the iOS device. The solution is to turn the 'Embed fonts' option on (this is done by opening the Project Properties dialog and going to the PDF Options section).

Now, the Embed fonts option is turned on by default. Since this will result in slightly larger PDF files, some developers might want to not embed fonts in generated PDF files. This can be done by setting the property in the Project Properties.

UX Component - Pre-render Option - Bulk Update - If you have a large number of UX components and you want to turn on the 'Pre-render at design-time' option for each UX component, opening each component, setting the property and then saving the component would be tedious. A new bulk operation allows you to automatically set this property in multiple UX components at once.

 

 

 

Xbasic - Regular Expressions - regex_valid() Function - The regex_valid() function can be used to test if a regular expression is valid.

 

Examples:


? regex_valid("[.+")
= .F.

 

The issue with the above failing regular expression is lack of a closing ']'.
 


? regex_valid("[.+]")
= .T.


? regex_match(".","[.+")
ERROR: Unmatched [ or [^ in character class declaration. The error occurred while parsing the regular expression: '[.+>>>HERE>>>'.
 

 

 

UX and Grid Components - <ProjectStyle> - Compact Styles - Certain of the built-in styles (e.g. 'Alpha') have a 'compact' option. If you set  <ProjectStyle> to 'Alpha' you can now specify that you want to use the 'compact' option by setting the  <ProjectStyle> to Alpha:compact . In an individual component that is set to use <ProjectStyle> as its style, you can override the global settings of 'compact' or 'non-compact' by specifying:

<ProjectStyle>:compact

or

<ProjectStyle>:notcompact

 

UX Component - List Control - Show/Hide List Column - A new method has been added to the List control that allows you to show or hide a List column.

Syntax:

<listObject>.showHideColumn(columnNumber,flagShow)

 

 

UX Component - Pre-render at Design-time Option - Warning Message - When you save a UX component that does not have the Pre-render Component at Design-time option turned on, a warning message now comes up telling you that it is recommended to turn this option on because of the significant speed improvement this options will give at run-time.

If you choose not to turn the Pre-render option on, you can specify that the message should not be shown again for this component, or for all components

If you choose to turn the option on you can specify that the option should automatically be set to 'on' for all future UX components that you create.

TIP: If you choose the option to turn on pre-render for all UX components, you can un-set the option by going to View, Settings, Preferences, UX Component.

Xbasic Functions - JSON_to_YAML() - YAML is a markup language that is sometimes used in place of JSON. This function converts JSON to YAML. YAML (yet another markup language) uses nesting to represent hierarchy.

Example

 

json = <<%str%
{
    "fname": "john",
    "lname": "public",
    "children" : [
        {"name": "callie","hobbies": ["minecraft","leggo"]},
        {"name": "griffin","hobbies": ["ballet"]}
    ],
    "address": {
        "street": "12 and main",
        "city": "Squares Ville",
        "State": "KY"
    }
}
%str%

 

?json_to_yaml(json)

 

fname: john
lname: public
children:
    - name: callie
      hobbies:
        - minecraft
        - leggo
    - name: griffin
      hobbies:
        - ballet
address:
    street: 12 and main
    city: Squares Ville
    State: KY
 

Note: This function is just a wrapper around the  extension::JSON class.

 

Xbasic Functions - JSON_from_YAML() - YAML is a markup language that is sometimes used in place of JSON. This function converts YAML to JSON.

 

yaml = <<%str%

fname: john
lname: public
children:
    - name: callie
      hobbies:
        - minecraft
        - leggo
    - name: griffin
      hobbies:
        - ballet
address:
    street: 12 and main
    city: Squares Ville
    State: KY

%str%

 

json_from_yaml(yaml)
= {
    "fname": "john",
    "lname": "public",
    "children" : [
        {"name": "callie","hobbies": ["minecraft","leggo"]},
        {"name": "griffin","hobbies": ["ballet"]}
    ],
    "address": {
        "street": "12 and main",
        "city": "Squares Ville",
        "State": "KY"
    }
}
 

 

Note: This function is just a wrapper around the  extension::JSON class.

 

 

 

UX and Grid Component - Live Preview - Edge - When you do a Live preview from the UX or Grid, you can now select Microsoft Edge as the target. (For Windows 10 and above)

UX Component - Google Visualization Libraries- Gantt - Because of a recent change Google made to how their visualization libraries are loaded, if you select the 'gantt' library, you would get a Javascript error. This is now fixed.

 

 

Alsp, the sample templates that are available when you create a new UX includes an update example for Google charts. This new component includes as Gantt chart, as shown in the second image.

 

 

Xbasic Arrays - DIMMing Arrays with Default Values - When you DIM a new array, you can now specify a default value for each array item. This is especially useful when DIMming arrays for use with .Net code.

Examples:

dim sb[6] as system::Text::StringBuilder = new system::Text::StringBuilder(1024)
? sb[1].capacity
= 1024
? sb[2].capacity
= 1024
...
 

 


dim nums[6] as n = rand()
? nums
= [1] = 0.680694580078125
[2] = 0.709716796875
[3] = 0.17425537109375
[4] = 0.60302734375
[5] = 0.752105712890625
[6] = 0.02587890625


dim strs[6] as c = Rand_String(6+int(rand()*10))
? strs
= [1] = "eimpzcugesd"
[2] = "chjhlwuzu"
[3] = "nioseq"
[4] = "gsrslnflqravo"
[5] = "rvaqfaqqu"
[6] = "joexbk"

 

 

Xbasic - AlphaDAO SQL::Resultset.toJSON() - The .toJSON() method has been changed so now it create a parseable JSON array of objects. Previously the .toJSON() method was used for an internal function and it generated a special format that was of no general use.

Contrast the AlphaDAO SQL::Resultset.toJSON() with the AlphaDAO SQL::Resultset.toJSONObjectSyntax() method. The later generates a CR-LF delimited string of JSON objects. To turn the output from this method into a parseable string, it is necessary to add the opening and closing square brackets and to terminate each line, except the last, with a comma.

Examples:

dim cn as sql::Connection
cn.Open("::Name::northwind")
cn.PortableSQLEnabled = .t.
cn.Execute("select customerid, contactname, city, country from customers where country = 'canada'")
rs = cn.ResultSet
? rs.tojson()
= [
{"customerid" : "BOTTM", "contactname" : "Elizabeth Lincoln", "city" : "Tsawassenn", "country" : "Canada"},
{"customerid" : "LAUGB", "contactname" : "Yoshi Tannamuri", "city" : "Vancouverr", "country" : "Canada"},
{"customerid" : "MEREP", "contactname" : "Jean Fresnière", "city" : "Montréal", "country" : "Canada"}
]

cn.Execute("select customerid, contactname, city, country from customers where country = 'canada'")
rs = cn.ResultSet
? rs.ToJSONObjectSyntax()
= {"customerid" : "BOTTM", "contactname" : "Elizabeth Lincoln", "city" : "Tsawassenn", "country" : "Canada"}
{"customerid" : "LAUGB", "contactname" : "Yoshi Tannamuri", "city" : "Vancouverr", "country" : "Canada"}
{"customerid" : "MEREP", "contactname" : "Jean Fresnière", "city" : "Montréal", "country" : "Canada"}

 

 

UX Component - Pre-render - Security and Server-side Show/Hide Expressions - The pre-render option for UX component can make a dramatic difference in the speed with which UX components are rendered. This is especially true of large UX components. Pre-rendering can result in 5 to 10x performance improvements in certain cases. However, if your UX component used security or server-side show/hide expressions to control the visibility of certain controls on the UX you were not able to turn the pre-render feature on.

Now, even if your UX uses security or server-side show/hide expressions, you can still use the pre-render option as long as you also turn on the Apply security and server-side show/hide expressions property.

When this property is turned on, the UX is not recomputed at run-time (as is normally the case when a UX which uses security and/or server-side show/hide expressions). Instead, at run-time, data are sent to the UX with information about what security groups the user is in, and which controls need to be hidden or shown as a result of evaluating server-side show/hide expressions. A client-side function will then hide the controls that should not be visible.

 

 

It is important to understand that when you turn on the option to apply security and server-side show/hide expressions client-side, the result is not as secure as applying security and server-side show/hide expressions on the server. That's because when security and server-side show/hide expressions are applied server-side, the HTML and data that are sent to the client does not physically include anything that should not be visible to the user.

But when apply these settings client-side, the HTML may contain sensitive information that the user could see by viewing the page source (even though this information is hidden on the page itself).

A side benefit of turning this option on is that any controls whose visibility is controlled by a server-side show/hide expression will be shown or hidden if any ajax callback sets the value of a session variable that is used in a server/side show expression.

 

UX Component - Action Javascript - SQLite Actions - Several new actions have been added to the SQLite Actions actions in Action Javascript.

The new actions are:

Get Fields in a Table - This action will get the fields in a table as well as some additional information. The onSuccess event handler gets an array of objects. The array has an entry for each field in the table. Each object in the array has these properties:

Delete a Database - Deletes the physical file for the SQlite database from the device.

Create a Table - Allows you to create a new table in a SQLite database. You can define the table structure and also the indices for the table. The image below shows the builder where you specify the table structure. The action will automatically drop any existing table with the same name.

 

 

Create a Table from Data - This action will create a new table from data (i.e. it will import data into a new table). The data from which the table is created is a JSON array of objects where each object represents a record. For example, if you specify the following data:

 

[

    {"id" : 1, "FirstName": "Bob", "LastName": "Smith", "Department" : "Sales"},

    {"id" : 2, "FirstName": "Terry", "LastName": "Jones", "Department" : "R&D"},

]

 

A new table with 2 records would be created. The fields in the table would be id, FirstName, LastName and Department and the type of each field (except the id field) would be TEXT. The type of the id field would be INTEGER.

NOTE: SQLite does not have Date or DateTime fields. Date and time values should be stored in TEXT fields and should appear in the data to be imported as string values.

When you specify the data from which the new table is to be created you have the following options:

When you specify that the data are to be computed by an Ajax callback you have two options

You can specify if a table already exists with the table name you specify that the existing table should be dropped. If you do not drop the existing table, the operation will fail.

You can also specify a batch size property. After the new table has been created (with no records in it initially), INSERT statements are executed to insert the data into the table. You can specify how many records should be inserted with each INSERT statement. The default batch size is 100, which means that each INSERT statement will insert up to 100 records into the table. If you set the batch size to -1, Alpha Anywhere will try to add the data to the table with a single INSERT statement. However, this may result in an INSERT statement that exceeds the maximum statement length supported by SQLite and the action will fail. If you set the batch size  to 1, Alpha Anywhere will perform one INSERT statement for each row of data to be added to the table. If you have a large amount of data, this could be slow. Therefore, if you want to optimize performance of this action, you will want to choose the largest batch size possible before the action fails.

If the action fails at any point while adding the records to the newly created table, the table is not created.

 

Import Data into a Table - This action is very similar to the Create a Table from Data action except that a new table is not created from the data. Instead, the data are imported into an existing table. All of the options for specifying the data that the Create a Table from Data action supports are supported by this action.

 

Delete All Records from a Table - This action deletes all of the records in a table.

 

UX Component - List Control and ViewBox Control - Text Select - A new property 'Allow text select' allows you to enable/disable the ability to select text in a List or ViewBox control. Previously this always defaulted to true. Now, this property defaults to false.

UX Component - List Control and ViewBox Control - Multi-select - Shift+Click - When doing a multi-select in a List or ViewBox that is configured to allow multiple selections, shift+click will now select multiple values, following the standard Windows conventions.

 

UX Component - FormView Control - Default Template and Named Templates - Formatting Directives - You can now use formatting directives in templates. For example:

 

Web Publishing - HTTP publish and Optimized Publish - These publish methods will now force a reload of the security data and will clear the UX component cache, so any changes should be reflected in the first request after publish.

UX Component - Action Javascript - PhoneGap File Download Action - This action has been enhanced. You can now specify that the list of files to be downloaded should be generated by making an Ajax callback. Of course, this same Ajax callback can also create the files to download (which is the most likely reason for choosing this option).

You can also specify where the file(s) that are downloaded should be stored in the device's filesystem.

You can set the Filesystem property to one of the defined locations. You can also set this property to the name of a Javascript function that will return the name of the Filesystem part, using this syntax:

javascript:myfunctionname

Your function must return the filesystem part (e.g. saved, private, public, persistent). Alternatively, you can return an explicit folder where you want to store files by prefixing the return value with 'explicit:' . For example:

 

function myfunctionname() {

    //return full path to folder with trailing /

    return 'explicit:file:///dir1/dir2/dir3/';

}

 

 

 

 


 

UX Component - Action Javascript - SQLite - Delete a Database - A new SQLite action has been added. The 'Delete a Database' action will delete a SQLite database file that had previously been downloaded to the device.

UX Component - List Control - Refresh List Data Action - Keep Focus - Child Records -  If you refresh List data and you select the option to keep focus on the current selection, child records (if any) will also keep their focus. Previously only the record in the parent List kept its focus.

 

 

UX Component - Captcha Controls - You can now define the style for the captcha control error message and you can control where the message is displayed.

 

UX Component - Application Cache - Spaces in Filenames -  If a file in the manifest had spaces in the name, the application cache was not created. This is now fixed as all filenames in the manifest are now URL encoded.

 

Bugs

UX Component - List Control - iOS Devices - List Freeze - Fixed an issue where the List control could freeze if it was being scrolled at the same time that the List was being repopulated. This issue could also have affected scrolling on PanelCards.

 

UX Component - Video Player Control - Action Javascript - SSL - YouTube - The action to set the YouTube video id was not honoring the SSL flag set in in the VideoPlayer properties.

 

UX Component - DetailView - Media Files - Incremental Refresh - After performing an incremental refresh on a List control, remote media files referenced in new data displayed in the List were not being fetched.

 

Xbasic - a5storage_listitems() Function - The a5storage_listitems() was limited to 1,000 items. Now, all of the items in the bucket are listed

 

UX Component - ControlBar Control  - Disclosure Button - Placeholders in Button Text - If a disclosure button had a placeholder in the button text, the placeholder was not resolved when the Disclosure was in its open state.

 

UX Component - List with Detail View - PhoneGap - Fetch Media Files - If a List with a Detail View was configured to fetch the media files referenced in the List from a remote server and store them in the file system on the device, when the PhoneGap app was loaded you would occasionally get a 'PhoneGap not ready' error message. This is now fixed. The reason for the error was that the method that downloads media files was firing before the PhoneGap ready event.

 

UX Components - Repeating Sections - Date Fields - If the client side date format for date fields in a Repeating Section did not match the server-side date format, when submitting data to the server, the client-side date fields in the Repeating Section were not being translated to the server-side date format.

UX Component - Client-side Calculated Fields - International Formats - If the client side decimal separator was set to a comma, then client-side calculated fields that involved decimal numeric fields were not being computed correctly. This bug was introduced in version 4.3.

 

UX Component - Ink Control - If a UX component was a child of a parent UX component, and the child UX component contained an Ink control, the Ink control would, in certain cases, not operate the second or subsequent time the child UX was opened.

Tips

Downloading Files to a Mobile Device - This topic discusses two different techniques for downloading files (such as PDF, Video, Audio, Excel, Image files) to a mobile device so that the files are stored in the filesytem on the device and can be viewer later on (presumably when the device no longer has an internet connection) using the Native app associated with the particular file type.

NOTE: The comments in this topic apply only to PhoneGap applications. Your PhoneGap application will need to load the following plugins: Cordova Open, Device, File, File Transfer.

The first technique uses the PhoneGap - File download action in Action Javascript. Using this action you can define an action that will download a list of files and store them in the filesystem on a mobile device. The action downloads a list of files returned by a Javascript function.

The second technique uses features of the List control to automatically download files when the List is populated. The data with which the List is populated should contain a field that has the URL for file you want to download. For example:

 
Filename URL
pdffile1 http://alphafiles.s3.amazonaws.com/pdffile1.pdf
pdffile2 http://alphafiles.s3.amazonaws.com/pdffile2.pdf
pdffile3 http://alphafiles.s3.amazonaws.com/pdffile3.pdf
pdffile4 http://alphafiles.s3.amazonaws.com/pdffile4.pdf
etc....  

 

To use this technique:

The advantage of this second technique over using the PhoneGap - File download action in Action Javascript is that the downloading of files is automatically handled for you.

 

 

 

 

 

Alpha Anywhere V4.3.1  -Build 3962-4772 14-Nov-2016

Videos

UX Component - Ink Control Image Annotation using the Ink Control in a Data Bound UX Component The ink control allows you to create sketches by 'drawing' with your mouse, any type of pointing device, or with your finger (on a device that supports touch). A common use of the ink control is to annotate images. The image you want to annotate is shown as the background to the ink control and then you can draw 'on top of' the image. When the data are saved the ink is stored separately from the image in a long text field.

In this video we show how a data bound UX component that allows a user to upload images can be configured to allow the user to annotate the images that are uploaded.


Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4

Download Component
Download SQL Table Definition

Date added: 2016-10-30
UX Component - ControlBar Control Defining Disclosure Forms using the Disclosure Form Builder In the video 'Displaying a Modal Pop-up Form using a Disclosure' we show how a modal pop-up form can be displayed using a Disclosure. The definition of the HTML for the form is fairly tedious because it is completely hand coded.

In this video we show how the Disclosure Form Builder can be used to make it easier to define the form HTML.


Watch Video - Part 1
Watch Video - Part 2

Download Component

Date added: 2016-10-30
UX Component ControlBar Control Display Modal Message Dialogs using Disclosures Modal messages (such as confirmations, progress, feedback) as commonly used when designing the user interface for an application. ControlBar disclosures make displaying these messages particularly easy.

In this video we show how the ControlBar can be configured to display three different types of message dialogs: basic information dialogs (one button), confirmation dialogs (two buttons) and wait dialogs (no buttons).

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Download Component

Date added: 2016-10-30
UX Component - List Control Specifying Sort Criteria when Filtering a List Action Javascript allows you to easily define fields on a UX where the user can specify search criteria for a List control on the UX ( much like the Search Part in a Grid). Now you can also define sort criteria.

In this video we show how the Filter Records in a List action in Action Javascript can be configured to allow sort criteria to be specified.

Watch Video

Download Component

Date added: 2016-1-03
UX Component - ControlBar Control Adding List Navigation Buttons to a ControlBar When you define a List control, you can specify that the List should be paginated. If you set the pagination method to 'Navigation Buttons' then you must define buttons to move to the next and previous page of records. In a mobile application that uses a ControlBar in a Panel header or footer, it is desirable to place these navigation buttons in the ControlBar.

In this video we show how you can quickly add List navigation buttons to a ControlBar by selecting the 'Pre-defined buttons' option when adding ControlBar items to your ControlBar definition.

Watch Video

Date added: 2016-11-05
UX Component - FormView Control Using a FormView Control to Edit Data in a List Control - Master-Detail Forms - Very Large Forms By default, when you configure a List with a Detail View (so that edits can be made to the List data), the Detail View is composed using individual controls (e.g. Textbox, Textarea, Dropdown, etc). If the Detail View has a large number of fields, then composing the Detail View using individual controls will be inefficient and will result is a very large UX component that may not perform well.

An alternative approach is to use the FormView control to implement the List's Detail View. This is extremely efficient and will allow you to build UX components that edit very large forms but still perform very well.

In this video we show how a master-detail Form is built using a FormView control to edit the fields in the Master table and a second FormView control to edit the fields in the Detail Table. The master table has 100 fields and the detail table has 100 fields, so in total, the UX component is editing 200 fields.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4

Download Component

Download Script to Create SQL Tables

Date added: 2016-11-08
UX Component - FormView Control Tutorial - Building a Mobile Master-Detail Form using The List, FormView and ControlBar Controls - In this video tutorial we show how a mobile app can be built to implement a master-detail form using the FormView control. The app will allow users to edit data from the Customers and Orders table in the sample Northwind database. This is a classic master-detail form: Each customer has multiple orders. The UX component uses two Lists joined in a parent-child relationship. The parent List displays data from the Customer table and the child List display the related orders from the Orders table.

Each List has a Detail View, but in both cases, the Detail View is implemented using the FormView control.

Once the basic functionality of the app has been built, the app is 'mobilized' by wrapping the various sections of the component in PanelCards and a ControlBar is added to implement navigation between the various parts of the application.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4
Watch Video - Part 5
Watch Video - Part 6
Watch Video - Part 7
Watch Video - Part 8
Watch Video - Part 9
Watch Video - Part 10

Download Components

Date added: 2016-11-10

 

 

 

 

UX Component - ControlBar Control - Buttons - Bubble Help - You can now define bubble help for all button types (button, button-list, button-toggle, disclosure-button) in the ControlBar control.

PhoneGap App Builder - Passcode Check Plugin - A new plugin for iOS has been added that allows the developer to verify that a passcode has been set on an iOS device. This an important security consideration if you are planning to store data on the device. If a passcode has been set on an iOS device, then the contents of the device are encrypted when the device is locked.

When the plugin is installed, a JavaScript PasscodeCheck object is automatically created after the PhoneGap ready event fires. You do not need to create this object. To use the plugin, call the isDevicePasscodeSet function.


PasscodeCheck.isDevicePasscodeSet(successCallback, failureCallback);


The successCallback and the failureCallback functions are required.

Success callback (called if device passcode is set with value of true)
Failure callback (called if the passcode is not set, with a value of false or on error or if the device does not support the LocalAuthentication framework)


Example:
 


PasscodeCheck.isDevicePasscodeSet(function() {
        alert('Passcode is set);
    },
    function() {
        alert('Passcode not set);
    }
);

 

PhoneGap App Builder - File Transfer Plugin - In early September, we detected a problem on Android devices with the latest version (as of 11/7/2016 : v1.6.0) of the File Transfer Plugin. A change was made to the PhoneGap Builder to load version 1.5.1 of the File Transfer Plugin, which is working reliably. If you have any Android apps that fail to upload media files, make sure version = "1.5.1" has been included in the project's config.xml file. If you do not feel comfortable editing the project's config.xml file, you can remove the file-transfer plugin, save the changes and then add the file transfer plugin once again and save. This will load the new plugin definition string that includes the version 1.5.1 specification. 


Action JavaScript - Stripe Checkout - Locale Property - Stripe has added support for a new locale property. The locale property is used to display the Stripe Checkout dialog in the native language of the user. The default value is auto and that will display Checkout in the users preferred language, if available. English is used by default. Supported languages include Simplified Chinese (zh), Danish (da), Dutch (nl), English (en), Finnish (fi), French (fr), German (de), Italian (it), Japanese (ja), Norwegian (no), Spanish (es) and Swedish (sv). Checkout also uses the locale to format numbers and currencies. 

PhoneGap Shell V2 - Overlay Button Position - You can now adjust the position of the overlay icon that shown when you are running a UX component in the PhoneGap shell. By default, the overlay button is shown bottom right. However, in some cases the overlay button will obscure an important part of the component you are testing and you will want to move it. To do so, click on the overlay button to show the bottom toolbar and then click the menu icon (left hand button).

 

This will show a dialog where you can adjust the overlay position.

 

UX Component - ControlBar - Pre-Defined Buttons - List Control Pagination Buttons - When you define a List control, you can specify that the List should be paginated. If you set the pagination method to 'Navigation Buttons' then you must define buttons to move to the next and previous page of records. In a mobile application that uses a ControlBar in a Panel header or footer, it is desirable to place these navigation buttons in the ControlBar.

When you add 'button' Items to a ControlBar, the Pre-Defined Buttons hyperlink opens a genie that makes it easy to add List control navigation buttons to the ControlBar.

Watch Video

 

UX Component - List Control - Action Javascript - Filter Records in a List Action - You can now specify sort criteria when using the Filter Records in a List action in Action Javascript.

Watch Video

 

UX Component - List Control - afterSelect Client-side Event - A new event has been added to the List control. The afterSelect event fires after a row in the List has been selected.

The afterSelect event is essentially the same as the onSelect event except in the case where the List has a Detail View and is the parent of a child List and the child List has been set to pre-fetch data. In this case the onSelect in the parent List will fire after the row in the parent List has been selected and the List's detail View has been populated, but before the child Lists have been populated. The afterSelect will fire after the child Lists have been populated.

 

UX Component - Client-side Events - onAjaxCallbackNotAllowed - The onAjaxCallbackNotAllowed client-side event fires if the server-side canAjaxCallback event does not allow the Ajax callback. I.e. the canAjaxCallback event sets:

e.authorized = .f.

 

UX Component - Client-side Data Cache - Deleting Items From Cache - You can now delete items from client-side data cache using the {dialog.object}.deleteFromDataCache() method.

 

Syntax:

{dialog.object}.deleteFromDataCache(itemName, onSuccessIn,onError)

 

Where

UX Component - Client-side Data Cache - Listing Files from the Cache that have been saved to disk - A new method allows you to list the files in the client-side data cache. These are the cache-items that are defined to persist to the filesystem and that have been retrieved. The syntax is:

{dialog.object}.listFileInDataCache([onSuccess [, onError]);

Where

 

UX Component - Client-side Data Cache - File Location - You can now specify where the client-side data cache files should be persisted in the file system (when running in PhoneGap).

To specify the location open the Client-side Data Cache editor and set properties on the Other Settings tab.

 

 

For backward compatibility select <default> for both the Filesystem and the Directory. This will store the files in the persistent filesystem (as specified by the PhoneGap constant LocalFileSystem.PERSISTENT). The files will be stored in a folder called __AADataCache/A5SessionFile.

If you specify an explicit Directory name or a Filesystem other than <default>, the A5SessionFile sub-folder in the target folder is not used.

The Filesystem and Directory can be dynamically set at run-time by calling a Javascript function.

For example, you could set the Directory to:

javascript:getDirectory

 

This would call a Javascript function called getDirectory. This function must return the name of the directory (with a trailing slash).

To specify an explicit location for storing the files in the client-side data cache, set the Filesystem property to the name of a Javascript function (for example javascript:getFilesystem). Your Javascript function should return the fully qualified URI of the folder where the cache files should be stored, prefixed with the string explicit: . For example:

function getFilesystem() {

    //return full path to folder with trailing /

    return 'explicit:file:///dir1/dir2/dir3/';

}

 

UX Component - ControlBar Control - Disclosure Form Builder - A new genie has been added to make building the HTML for simple Disclosure forms easier.

 

Watch Video - Part 1
Watch Video - Part 2

 

Xbasic - JWT - JSON Web Tokens - New methods have been added to create and decode JSON Web Tokens (JWT)

 

Example:

 

dim secret as c = "thisismykey"

dim token as c = extension::JSON::JWTSign(json_sanitize("{ fname : 'john' , lname : 'smith'}"),secret)
?token

= "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmbmFtZSI6ImpvaG4iLCJsbmFtZSI6InNtaXRoIiwiaWF0IjoxNDc3ODMzMDgwfQ.RJ7vNIYtUaC5DNXiJtiQpxKYUO2TRW2U9bpFZMPypw4"

? extension::JSON::JWTVerify(token,secret)

= {"fname":"john","lname":"smith","iat":1477833068}

 

UX Component - List Controls - Events - The way in which events are handled for buttons, hyperlinks and dynamic images in a List control has been changed to use 'items' (i.e. the 'a5-item' attribute), rather than binding events to the buttons, hyperlinks and dynamic images in each row. This new method is substantially more efficient than the previous method and will result in less memory utilization and better performance. The performance differences in large lists with several buttons, hyperlinks etc. in each List row should be especially noticeable.

 

UX Component - Image Annotation using Ink Control in a Data Bound UX Component - A great use case for the Ink control is to annotate images. This is done by displaying the image you want to annotate as the background to the Ink control and then the user can 'draw' on top of the image.

New properties have been added to the UX to allow you to easily configure the Ink control to use an image as its background. The image is and the ink annotation are stored in separate fields in a database.

The image below shows an Ink control with an image as its background.

When you configure the UX you specify that it is data bound to the table that contains the images and the ink annotation. You bind the image field in the table to an image control on the UX and you bind the annotation field in the database to the Ink control on the UX. The in the Ink control's Data Binding section you specify the name of the image control to use as the ink background.

 

 

Application Server - a5w_info() Function - Changes have been made to the a5w_info() function to give additional information under IIS and the AlphaCloud. The changes are summarized below:

 

1. The System section at the bottom now includes values that tell you the operating system and version of the server.

For example:

 

Server Product                         ApplicationServerIIS
Platform                               Windows
Operating System Name                  Microsoft Windows Server 2008 R2
Operating System Version               6.1
Operating System Is Server Edition     True
 


The XBasic required to generate those values is below.


? Context.ApplicationConfiguration.ServerProduct
= “ApplicationServerClassic”

?OSPlatform()
= "Windows"

?OSName()
= "Microsoft Windows Server 2008 R2"

?OSVersion()
= "6.1"

?OSIsServerEdition()
.t.
 

 


2. The ServerSetting section is specific to the Classic edition of Alpha Anywhere Application Server. This section is no longer generated unless the value of Context.ApplicationConfiguration.ServerProduct is ApplicationServerClassic; which apples to Live Preview as well.

The full set of values available is currently:

 

 



3. There is an Alpha Cloud section that is displayed only when the server product is AlphaCloud.

This section shows the application constants generated by Alpha Cloud on deployment, including the subscription, account, application, deployment, published version and publication creation date/time and the deployment date/time..

4. On the Request section, many of the values on a5w_info() showed the names of object properties and functions rather than the values of interest.


For all servers Session.Keys was not working. It now displays the keys for session values.

For IIS (and Alpha Cloud), the following were not showing values, but object function and property names instead. These now display the keys and values in nested tables:

 

 


 

Bugs

UX Component - Javascript Error in _numberStringSanitize Function - In certain cases a UX would give Javascript error when loading. The reported error was in the _numberStringSanitize method of the UX component.

UX Component - Caching - A bug in the way the UX component was being cached was fixed. This bug could, in certain cases, lead to a server crash.

Desktop Forms - Supercontrols - Google Maps - Because of a change Google made to their Maps API, the Google Maps supercontrol will no longer work. However, the Bing or Mapquest supercontrols can be used as alternatives.

Reports - Layout Table Reports - Fixed an issue with high order characters.

Web Applications - Web References - Fixed an issue with the proxy generator.

 

Tips

Grid Component - Alpha Theme - Icons - When you use the new 'Alpha' theme in a Grid, the toolbar icons for the Detail View can be a little hard to see  in their default state (see first image).

However, you can make the icons much clearer by applying some CSS to the SVG icons used in the toolbar (see second image)

 

 

To define the necessary CSS select the Local CSS definitions property.

 

 

Specify the following CSS:

.grid .link .icon { 
    fill: #333;
    stroke: #333;
}
 

 

 

 

Alpha Anywhere V4.3  -Build 3922-4757 26-Oct-2016

VERY IMPORTANT: As of build 3898 if the regional settings on your server do not use a period as the decimal character and if the client-side number format that users will use when entering numbers does not use default settings  (period for decimals and comma for thousands separator) then you must set the new Number format - decimal character  and  Number format - thousands separator properties in each UX component. See the UX Component - Number Formats topic below for more information.

 

Summary: V4.3 is packed with new features. Perhaps the single most important new feature is the ControlBar control in the UX component. If you are building Mobile apps, the ControlBar will give you a huge productivity boost and allow for much more professional looking applications. It is an essential tool for Mobile app developers! Other new features of note include the new 'Alpha' stylesheet, new PhoneGap shell for quickly testing PhoneGap applications, Built-in SVG icons for all themes, Google address auto-complete

Videos

UX Component - FormView Control Capturing Signatures using the SignatureInk Editor A common requirement when using the FormView control is capturing a signature. Alpha Anywhere has a Signature control, but this control captures signatures as bitmaps and is not ideal for use in a FormView control. The Ink control is better suited for this use case.

In this video we show how a FormView control is configured to use the built-in SignatureInk editor.

Watch Video

Download Component
Date added: 2016-06-30
 
Node Installing a Node Module from NPM and then Creating a Node Service to Call Methods in the Node Module The Xbasic code you write in your Web applications can call methods in Node.js modules that are installed from NPM (the Node Package Manager).

In this video we show how a Node module is installed into the Web Project folder and then how a Node Service is created so that methods in the Node module can be called.

The particular Node module that we install in this video is called Tinify and we show how a Node Service is defined so that we can call into this module from Xbasic using the Node_request() function.


Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Date added: 2016-07-06
 
UX Component - Ink Control Customizing the Ink Control Overlay The Ink control 'overlay' displays a number of tools that are used by the Ink editor (such as the Pen selector, Eraser, etc.). You can customize the appearance of the 'overlay' and add your own tools (i.e buttons).

In this video we show how you can add a new button to the Ink editor overlay.

Watch Video


Date added: 2016-07-08
UX Component - Ink Control Setting the Ink Control Background Image Setting the background image in the Ink Control is a common practice. In this video we discuss various aspects of how you can set the Ink control image background and control whether the UX goes dirty when the Ink background is set.

Watch Video - Part 1
Watch Video - Part 2


Date added: 2016-07-06
UX Component - Ink Control Using the Ink Control to Capture Signatures The UX Component has always had a built in Signature Capture control. However, it is also possible to use the Ink control to capture signatures. The primary benefit of using the Ink control to capture signatures is that the signature is captured using the Ink format, which is an ascii format, rather than as a PNG image, which the Signature Capture control uses.

In this video we show how to configure the Ink control to capture signatures.

Watch Video


Date added: 2016-07-08
UX Component - ViewBox Using a ViewBox as the List's Detail View A common pattern when building mobile applications is to use a List control with a Detail View. When the user taps on a row in the List, the Detail View shows the details for the selected row. This pattern is used extensively, especially for offline applications where the data in the List is intended to be updateable.

However, there are many cases where the List is not intended to be  updateable and a much 'lighter weight' solution can be achieved but not turning on the List's 'Has Detail View property' and instead, using a ViewBox to display details for the selected row in the List.

An even lighter weight solution can be achieved by using a ViewBox to replace the List. So you end up with a ViewBox to display a list of records and another ViewBox to display details for the selected record.

Watch Video - Part 1
Watch Video - Part 2

Download Component

Date added: 2016-07-09
UX Control Building a Custom Image Gallery using the List and Ink Control The List and Ink Control can be used to build a custom Image Gallery in which the List is used to display thumbnails of the available images and when the user taps on a particular image, the full size image is shown in the Ink control. The advantage of using the Ink control to display the image is so that you can take advantage of the Ink controls pinch-zoom features and pan features to scale the image and to pan around to see details of different parts of the image. The ability to actually draw ink (which of course is the primary purpose of the Ink control) is not used in this case.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Download Component

Date added: 2016-07-16
UX Component - List Control Options for Handling Write Conflicts when Syncing Data When you build a disconnected mobile application, there is always a chance that the user will get a write conflict when they sync data that was edited while they were offline. This could  happen because some other user has committed a change to a record before another user could commit their change.

By default, when a write conflict occurs, the information about the conflict is sent to the user and the user can resolve the conflict by selecting 'Their value' or 'My value'. However, there are other powerful programmatic options for handling write conflicts. In this video we discuss the various techniques for handling write conflicts.

Watch Video - Part 1
Watch Video - Part 2


Date added: 2016-07-21
Grid Component Preventing User from Closing Pop-up Window if Grid or a Linked Child Grid is Dirty It is common in web applications to have buttons that open a Grid component in a pop-up window. The Action Javascript builder when you build this action has a built-in property that allows you to prevent the user from closing the window if the Grid shown in the window is dirty. But what if the Grid shown in the window has Linked child Grid components? You might want to also check that the child Grids are not dirty before the window can be closed.

In this video we show how this can be done.

Watch Video

Date added: 2016-08-04
UX Component - FormView Control Creating Complex Form Layouts using the Flow and Column Layout Containers When you lay out a Form using the FormView control, by default, the controls on the form are rendered with one control per line and each control taking up the full width of the FormView control. If you want to create a more complex Layout you can either switch from Genie mode to the Freeform mode, or you can use Flow and Column Layout Containers to control the layout of your Form.

In this video we show how a complex Form layout is achieved using Column and Flow layout containers.

Watch Video - Part 1
Watch Video - Part 2

Download Component

Date added: 2016-08-27
UX Component Adjusting Colors and Fonts in a Stylesheet Alpha Anywhere has always allowed you to edit a stylesheet used by a component to change any of the CSS defined in the stylesheet. But when you simply want to change some colors in a stylesheet, using the style editor may be more than you need.

In this video we show how you can easily adjust colors and fonts in a style.

NOTE: This option is only available for 'new' styles (AndroidLight, AndroidDark, iOS7, Alpha) as these styles are based on SASS.

Watch Video

Date added: 2016-09-14
UX Component - ControlBar Control Introduction to Basic Concepts This video demonstrates basic concepts of the ControlBar control.

Watch Video - Part 1
Watch Video - Part 2

Date added: 2016-09-14
UX Component - ControlBar Control Updating ControlBar Data - Dynamic Text This video demonstrates how you can update the data in the ControlBar's data. This allows you to put dynamic text in the Controlbar. We also show how the ControlBar can be animated when it is refreshed.

Watch Video - Part 1
Watch Video - Part 2


Date added: 2016-09-14
UX Component - ControlBar Control Using Watch Events to Update ControlBar Data The ControlBar data can be updated automatically in response to certain events in the UX (such as the UX going dirty, a List going dirty, etc.) or by a change in the value of one or more controls.

In this video we show how you can configure watch events to automatically update ControlBar data.


Watch Video

Date added: 2016-09-14
UX Component - ControlBarControl Adding a Button to a ControlBar In this video we show how you can add a button to a ControlBar and then associate an action (i.e. some Javascript code) to run when the button is tapped.

Watch Video
Download Component

Date added: 2016-09-14
UX Component - ControlBarControl Adding a Button-Toggle to a ControlBar In this video we show how you can add a Button-Toggle to a ControlBar. Toggle buttons can either be two-state (switching between a true and a false state), or multi-state (each click advances to the next button state).

The video shows how the state of a Button-Toggle is used to control what action a button performs when clicked.

Watch Video
Download Component

Date added: 2016-09-14
UX Component - ControlBarControl Adding a Button-List to a ControlBar A common pattern in mobile apps is to have a button bar at the bottom of the screen with a series of buttons that allow you to select the active Panel that is shown on the device. Typically, these buttons are spread out so that they fill the width of the screen.
The button-list control is ideal for implementing this pattern.

In this video we show how a Button-List can be configured to fill the width of the screen and to select a Panel Card in a Panel Layout when one of the buttons in the Button-List is tapped.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3


Download Component

Date added: 2016-09-14
UX Component - ControlBar Control Selecting the Active ControlBar Layout A ControlBar can have multiple Layouts. In this video we show how you can dynamically select the Layout to show.

Watch Video - Part 1
Watch Video - Part 2


Download Component

Date added: 2016-09-14
UX Component - ControlBar Control Showing a Disclosure A disclosure can be some explicitly defined HTML, or it can be another Layout. In this video we show how a disclosure, defined as a ControlBar layout, is shown.

Watch Video
Download Component

Addendum: One of the more unusual disclosure types is Outside-After (and Outside-Before) which display the disclosure perpendicular to the parent Layout. In this video we show how the disclosure is rendered when the Outside-After type is selected.

Watch Video - Part 2

Date added: 2016-09-14
UX Component - ControlBar Control Showing a List in a Disclosure You can display standard UX controls (such as Lists, Buttons, Input controls, etc.) in a disclosure. In this video we show how a list is displayed in a disclosure.

Watch Video - Part 1
Watch Video - Part 2


Download Component

Date added: 2016-09-16
UX Component - ControlBar Control Setting the Selected Button in a Button List using Javascript The selected button(s) in a ControlBar Button List can be set programmatically using Javascript. It is also possible to completely change the buttons shown in a Button List programmatically.

In this video we show how this is done.

Watch Video

Download Component

Date added: 2016-09-21
UX Component Google Address Auto-complete A commonly seen feature in many web and mobile applications is address auto-complete. As the user starts typing an address into a textbox, a list of suggested address is shown and the user can select from the list. This feature is powered by Google Maps.

In this video we show how you can turn on the Address Suggest feature for any textbox control on a UX.

NOTE: Textbox controls in Repeating Sections are not supported.

Watch Video - Part 1
Watch Video - Part 2


Date added: 2016-09-16
UX Component - ControlBar Control Defining Javascript in a ControlBar - Understanding the 'This Object' Option. Using Javascript function in a template. When you define Javascript functions in a ControlBar (and also a ViewBox and FormView control), you can specify where the Javascript should be stored. The options are: At the control level, at the UX level and 'This object'.

This video explains the options and discusses why the 'This object' option is best. It also describes how functions defined at the 'This object' level can be referenced in templates.


Watch Video
Download Component

Date added: 2016-09-28
UX Component - ControlBar Control Dynamically Showing and Hiding Lines in a ControlBar Layout A ControlBar layout can have multiple Lines. Each Line in a Layout can be dynamically shown or hidden.

This video shows how a show expression can be defined for a Line in a ControlBar Layout


Watch Video
Download Component

Date added: 2016-09-28
UX and Grid Component Sending SMS Messages using the Twilio Service You can send SMS messages from the Grid and the UX. The messages are sent using the Twilio service, so you will need a Twilio account. You can use Action Javascript to define the action which sends the message.

There are a large number of options for customizing the message, such as sending messages in different languages, depending on the user preference.

In this video we show how a button was defined in the UX to send a message. The phone number and message body are read from controls on the UX.

Watch Video

Date added: 2016-09-29
UX Component Creating Offline HTML5 Applications using the Application Cache The Application Cache (an HTML5 feature widely supported by various browsers) allows you to build 'offline' applications - i.e. applications that can be loaded into the browser even if there is no internet connection. In order to load the application initially an internet connection is obviously needed. But once the application has been loaded initially, all of the files (e.g. CSS.Javascript, images, etc.) referenced by the application are cached in the browser and an internet connection is not needed to load the application subsequently.

If the application is updated, then if an internet connection is available when the app is loaded, the new version of the app is downloaded and cached in the browser.

In this video we show how offline HTML5 applications can be created using the Application Cache feature.

NOTE: These 'offline' HTML5 applications do not require PhoneGap!

Watch Video - Part 1
Watch Video - Part 2

Date added: 2016-09-29
UX Component - List Control Saving and Restoring List Settings to Quickly Define New Lists The List control is one of the most commonly used controls in a UX component. But because of the richness of the List, there can be many properties that need to be set to configure a List. After you have configured a List, you can save all of the settings for the List in a named file. Then when you define your next List, you can restore the settings from the named file - saving a lot of time.

This video demonstrates how List settings can be saved and restored.

Watch Video

Date added: 2016-109-02
UX and Grid Component Using the Javascript Code Library The Javascript Code Library is available in all contexts where Javascript can be edited. The Code Library is ideal for storing snippets of code that can then be pasted into the Javascript you are editing.

In this video we walk through the various features of the Javascript Code Library.

Watch Video

Date added: 2016-109-05
UX Component - ControlBar Control Adding an Edit ControlBar Item to a ControlBar A ControlBar typically contains text and buttons, but a common use case is to build a Search ControlBar that uses an edit control in the ControlBar.

In this video we show how the edit ControlBar item type can be used to build a Search feature.


Watch Video
Download Component

Date added: 2016-10-08
UX Component - ControlBar Control Displaying a Modal Pop-up Form using a Disclosure A common pattern in many applications (both Mobile and Desktop web) is to display pop-up modal forms to collect some information from the user. Displaying pop-up modal forms using the ControlBar is very easy and extremely powerful.

This video shows how a ControlBar 'disclosure' is used to display a pop-up modal form. The 'a5-action' attribute in the Disclosure HTML is used to invoke actions defined in the ControlBar's Action pane.


Watch Video - Part 1
Watch Video - Part 2

Download Component

Date added: 2016-10-08
UX Component - FormView Control Displaying Calculated Values on a FormView Control When you design a FormView control you may want the form to display calculated values (typically computed from other fields in the form). Since the Form is really just an HTML template that is rendered using Alpha Anywhere's client-side templating features, this is easily done.

In this video we show how a calculated field is added to the FormView control.

Watch Video
Download Component

Date added: 2016-10-10
     

 

 

 

Features

UX Component - ControlBar Control - A new control type is available in the UX component. The ControlBar is primarily intended for creating the content that appears in Panel headers and footers and it is a much easier and vastly more flexible way for populating a Panel header or footer compared with the previous technique of adding standard UX controls (such as buttons and static text controls) to the header or footer.

For more information on ControlBars, please see the User Guide documentation here.

You can also refer to the API documentation here.

To see videos on the ControlBar refer to the Videos section of this document.

 

UX Component - ControlBar Control - Modal Dialogs - A new property (Auto-hide disclosure) for disclosure-buttons allows the disclosure opened by the disclosure-button to be modal. This means that the user will not be able to tap anywhere off the disclosure to close the disclosure, but must tap a button on the disclosure itself in order to close the disclosure. To make a modal disclosure:

For example, in the image shown below when the user taps the Settings button, the disclosure (a modal dialog) prompting for two input fields is shown. The user cannot close the disclosure by clicking off the disclosure. The only way to close the disclosure is by tapping the OK or Close buttons.

 

 

UX Component - ControlBar Control - Miscellaneous Improvements

When you define HTML for a Disclosure you can now use the a5-actions attribute in your HTML to bind to ControlBar Actions. For example:

<div a5-action="action1">

    Tap here to do some task

</div>

A new type of ControlBar Item is available. The Edit item allows you to display an input control in the ControlBar.

The button-disclosure ControlBar item now supports user defined events such as click, downhold, etc.

 

UX Component - ControlBar Control - Samples - When you open the ControlBar builder you can now get a quick start by loading a sample ControlBar. On the 'Home' tab in the ControlBar builder, click the Load Sample ControlBar hyperlink.

 

 

UX Component - ControlBar, ViewBox and FormView Controls - Defining Javascript - In the builder for the ControlBar, ViewBox and FormView, you can define Javascript functions.

When you define you Javascript functions, you can specify where the Javascript should be stored. The options are:

Now, a new option is available:

When you select the 'With the control' option, the Javascript is stored in the control definition, (which means that if you copy the control to another UX component, the Javascript you define comes along - this would not be the case if you use the 'With the UX' option). However, at render-time for both the 'With the control' and 'With the UX' options, the Javascript functions you define are global functions. That means that if you have a UX with multiple ControlBar, ViewBox or FormView controls, and they each define a different function called (say) 'func1' at the 'Wit