The V10 Grid component has been completely rewritten to use Web 2.0 Ajax features. A huge number of new features have been added to the Grid and the Grid performance is now dramatically faster than the V9 Grid component.
'Alphabet' buttons provide a convenient metaphor for searching for records in your Grid. When you click on a particular alphabet button, the Grid is filtered to show all records in a specified field that start with the letter that you clicked. For example, if you specify that your Alphabet buttons should search on the lastname field, when you click on the 'B' button, all records with lastnames that start with 'B' are shown.

'Alphabet' buttons showing 'hyperlink' style buttons.

'Alphabet' buttons showing 'button' style buttons.
You can position the 'Alphabet' buttons inside the Grid, as shown in the above two images, or outside the Grid, as shown below.

'Alphabet' buttons showing how the buttons can be positioned outside the Grid.
You can configure your 'Alphabet' buttons to also show buttons for 0 through 9 by checking the 'Include numeric buttons' property.
You can configure your 'Alphabet' buttons to show as choices in a dropdown box rather than as a list of buttons or hyperlinks by setting the button style to 'Dropdown'.

'Alphabet' buttons configured to display as a dropdown.
You are not limited to a pre-defined list of buttons showing A through Z when you turn on the Alphabet buttons feature. You can completely customize the buttons that are shown in the button bar and the corresponding search that is performed when you click a button. To customize the buttons, select 'Custom Buttons' in the 'Search bar type' prompt. Then click the smart field in the 'Custom search definition' property. The following dialog will appear:

The button definition is to the left of the equal sign and the corresponding filter expression is to the right of the equal sign.
You can display arbitrary HTML as the button definition (as long as you set the button style to be button or hyperlink - not dropdown). This means (for example) that you can include images in the buttons.
The Search Part in the Grid can be configured to allow Query by Form (QBF) syntax. QBF search now supports != operator. If you have configured the Search Part to allow QBF syntax, you can now use != to search for records that are not equal to a particular value. The complete list of QBF operators is shown below:
| Operator | Example | Meaning |
| = | =alpha | equals 'alpha' |
| > | >10 | greater than 10 |
| <= | <= 12/18/1952 3:23 PM | less than or equal to 12/18/1952 |
| < | <10 | less than 10 |
| <= | <=23 | less than or equal to 23 |
| != | !=alpha | not equal to 'alpha' |
| value1..value2 | alpha..beta | values that are >= 'alpha' and <= 'beta'. If the field you are searching is a time field (which has a date and time portion), and you omit the time part from value2, Alpha Five will automatically add a time part of 23:59:59 PM to the timer part. |
| ..value2 | ..12/1/2008 | values that are less than or equal to 12/1/2008. Note: If the field you are searching is a time field, and you omit the time part, Alpha Five will automatically search for values less than or equal to '12/1/2008 23:59:59 pm' |
| value1.. | 23.. | values that are greater than or equal to 23 |
| Is blank | Is blank | Values that are blank or null. (To omit null values use = '' instead of 'Is blank' ) |
| Is not blank | Is not blank | Values that are not blank or null. |
| Is null | Is null | Values that are null (SQL databases only) |
| Is not null | Is not null | Values that are not null (SQL databases only) |
| value1,value2,value3 | alpha,beta,gamma | values that are 'alpha' or 'beta' or 'gamma' |
If you define a Search Part in a Grid and include a Time field in the Search Part and set the Time field to be a Range search, then if you enter a TO value that does not include a time part, a time part of "12:59:59 pm" is automatically added. This makes it easier to search for records in a date range.
For example, lets say you have 3 records with time values of '1/1/2009 10:00 am', '1/1/2009 3:15 pm' and '1/1/2009 6:45 pm'. Previously, if you entered a start time of '1/1/2009' and and end time of '1/1/2009' the search would have found 0 records. Now, it will return the 3 records on 1/1/2009.
Similarly, if you use the QBE syntax, and you enter a search value of 1/1/2009..1/1/2009, Alpha Five will convert that search to 1/1/2009..1/1/2009 12:59:59 pm.
A new option allows you to use Grid column headings in the 'Sort by' dropdown box. By default, field names are shown in the dropdown box.
Property name: 'Record navigator layout' ('Properties' pane)
You can now select the target page by typing the page number into an edit box and pressing Enter. The benefit of this method of page navigation is that it gives you direct access to any page in the Grid. By contrast, the V9 and earlier technique of providing page links can only allow you direct access to a limited number of pages that are close to the current page.
To turn on this feature, open the 'Record navigator layout' genie and check the 'Use type-in box for page navigation' checkbox.
![]() |
Setting the page navigation style |
![]() |
Record navigator showing type-in box for page navigation |
![]() |
Record navigator showing V9 style page links. |
Property name: 'Row edit style' ('Update Properties' pane)
Previously, if a Grid was updateable, then all of the rows in the Grid would be displayed using edit controls for each field (i.e. TextBoxes, TextAreas, etc.).
Now, there is a new option called 'Edit On Demand'. When you select this option, the Grid is shown as using labels for each control. You can then double click on a field, or click the Edit icon, to turn that row into edit mode. You can specify if more than one row at a time can be in edit mode. If only one row is allowed in edit mode at a time, then when you put another row into edit mode, the row that is currently in edit mode is turned back into view mode.
![]() |
All rows are editable (V9 and older style) |
![]() |
Grid rows are editable on demand |
![]() |
Row 1 of the Grid has been put into edit mode |
The Grid Component allows you you to add JavaScript code to your Grid. There are a large number of events for which you can define Javascript event handlers.
In many cases, you can use Action Javascript to help you write the Javascript. For example, if you put a button in the Grid (by selecting the Insert... hyperlink underneath the list of fields), you can use Action Javascript to define the code to open a new Grid that is linked to the current row, or print a Report.
The image below shows the Javascript editor to define the Javascript for the 'click' event on a button.
You can define the code using either Action Javascript, or 'Text mode' - which switches the editor to a text area where you can type in any code that you want.
If you switch to Text mode after you have already defined actions using Action Javascript, the code for the Action Javascript is shown in the editor. This is an excellent way of using the Genie to get started and then enhancing the code with your own code.

To add a new action using the Action Javascript editor, click the 'Add New Action' button and make your selection from the list of actions (shown below).

You can right click on an action in the Action Javascript editor and select commands. One of the available commands is 'View Javascript' which shows you the Javascript that was automatically generated for you. Depending on the action, the Javascript might be divided into several pieces - some that is inserted directly into the control (e.g. in the control's onclick attribute) and some which is inserted into functions.
The list of actions from which you can choose include:
| Message box | Display a Javascript alert box on the screen. |
| Open a Grid component | Open a Grid component in a pop-up window, or in a DIV on the current page. If the Grid is running inside a Tabbed UI component, can also open the target Grid in a new pane in the Tabbed UI. The target Grid is typically filtered using data from the current record. |
| Open a Report, Label or Letter layout | Display a report, label or letter layout as a PDF file using the Acrobat PDF reader. The report is displayed in either a pop-up window, or in a DIV on the current page. If the Grid is running inside a Tabbed UI component, can also open the target Report in a new pane in the Tabbed UI. |
| Open a web page in a pop-up window or a DIV | Open a web page (including .a5w pages, static .html pages, or any other web page, e.g. www.google.com) in a modal, or modeless pop-up window, or in a DIV on the page. This action also opens 'Supercontrols' - automatic links to Google Maps, Google Search, MSN Maps, etc. |
| Inline-Javascript | Allows you to enter some hand-coded Javascript code. |
| Ajax Callback | Define a user-defined ajax callback. The callback can be handled by an Xbasic function that is defined in the Grid component, by a separate .a5w page, or by another page (.e.g. .php, .asp, .aspx, etc.) page. |
| City, State Lookup from Zip Code | For a given zip code, lookup the city and state on the USPS web site and fill in the city and state in the current record. |
| Zip Code Lookup from Address | For a given address, lookup the Zip code on the USPS web site and fill in the Zip code field in the current record. |
| Lookup and Fill-in Fields | Lookup values in a table and fill-in fields in the current row from fields in the Lookup Table. See below for more details. |
| Set Page Content | Set the content in one or more page elements (i.e. 'divs', 'spans', form fields, etc.) to values obtained from fields in a Lookup Table. See below for more detaisl. |
The 'Lookup and Fill-in Values' allows you to perform an Ajax callback to find a matching record in a Lookup Table and then fill-in fields in the record you are editing with data from the Lookup Table. Features of this action include:
Examples of where it might make sense to use this action include the OnClick event of a button, or the OnBlur event of an input control.
This action allows you to set the content of parts of a page (e.g. 'div', 'span', 'iframe' and other elements) with content that comes from a database. This action makes an Ajax callback to the server to find a record that is 'linked' to the current record in the Grid, and then it sends back the appropriate Javascript response to the browser to set the content of the specified page elements.
For example, say that the .a5w page in which you have placed a Grid has a div with an id of 'content1'. Every time you click on a different row in the Grid, you want to make an Ajax callback to the server to find the record in a lookup table that is linked to the current row in the Grid, and then you want to set the data in the 'content1' div to the value of the 'HTMLNotes' field in the lookup table. The 'Set Page Content' action can be used for this.
The 'Set Page Content' action can actually be used to set any Javascript property of any element on a page to a value that is computed on the server using data from the lookup table. For example, it could be used to set the src property of an IFrame, or the src and title property of an Image, or the style property of a div, etc.
When you select this action, the following builder is displayed:

This allows you to define the lookup table, and how it is linked to the data in the current record.
Once you have defined the lookup table, you can click the smart field for the 'Definition' to define the rules for what content gets filled-in. This dialog looks like this:
You can define as many rules as you want.

To define a new rule, click the 'Add Action' button. This dialog allows you to add a new action.
If you use 'Advanced' mode in the above dialog, then you can write an arbitrarily complex Xbasic script to generate the Ajax response that is sent to the server.

You can define Javascript event handlers at many levels in the Grid component (e.g. at the control level, at the row level). Your Javascript event handlers can make Ajax callbacks. The callbacks can submit data from the current row in the Grid. If you have turned on the 'checkbox' column, then data from the checkbox column is also returned. The callbacks can be handled by an Xbasic function that is defined in the Grid component, or by a separate page (could be an .a5w page, a PHP page, .ASP page, or any other type of page).
To have your Javascript function make an Ajax callback, you use the '.ajaxCallback()' method of the Grid object.
The syntax for this method is:
Handling the callback with a function defined in the Grid component:
<GridObject>.ajaxCallback(part, rowNumber, XbasicFunctionName)
If you want to pass back some data in the callback, you can do so using this syntax:
<GridObject>.ajaxCallback(part, rowNumber, XbasicFunctionName,'',OtherData)
Handling the callback with a separate page:
<GridObject>.ajaxCallback(part, rowNumber, ActionName, URL, OtherData)
Where:
| part | 'g' - if you want to submit data from the current row in the Grid part, or 'd' - if you want to submit data from the currently open DetailView record |
| rowNumber | If part is 'g', the row number whose data you want to submit. If part is 'd' then must be 1. In the case where part is 'g', and the rowNumber is set to 'all', data from all of the rows in the grid is submitted. If rowNumber is set to 'none', no data will be submitted. |
| XbasicFunction | The name of the Xbasic function that will handle the callback. This function is defined in the 'Xbasic function declarations' section. IMPORTANT: The 4th parameter (URL) must NOT be specified. |
| ActionName | Applies only if the URL parameter is specified. See definition of URL. |
| URL | The URL of the page that will handle the callback. A variable called '_action' is passed to the URL. The value of _action is set to ActionName. |
| OtherData | Name value pairs of any other data you want to submit as part of the callback. |
For example, assume that you have placed a button in a Grid column. When the user clicks the button, you want to make an Ajax callback, passing back the data in the current Grid row. Here is the Javascript that you would define for the button's onClick event:
{grid.object}.ajaxCallback('g',{grid.rowNumber},'function1');
When the Grid is rendered, the {grid.object} placeholder will get replaced with the actual Grid object name (based on the Alias assigned to the Grid at run-time) and {gird.rowNumber} will be replaced with the row number. So, for example, if the Grid alias was set to 'Grid1' then the Javascript in the button on row 1 would be:
GRID1_GridObj.ajaxCallback('g',1,'function1');
If you wanted the callback to be handled by a separate .a5w page (called 'callbackpage.a5w'), you could use this Javascript in the button's onClick event:
{grid.object}.ajaxCallback('g',{grid.rowNumber},'myActionName','callbackpage.a5w');
If you wanted the callback to be handled by a PHP page on a totally different server:
{grid.object}.ajaxCallback('g',{grid.rowNumber},'myActionName','http://www.mydomain.com/callbackpage.php');
In the case where the callback is handled by a function that is defined as part of the Grid, you must use the following prototype for the function:
function callbackfunctionName as c (e as p)
end function
The 'e' argument contains all of the data that is submitted on the callback. To see what's in 'e', use the Firebug addin for Firefox and examine the contents of the 'Post' tab in the Firebug window after a callback has occurred.
In addition to the data that was submitted on the callback, 'e' also contains:
In addition to the above, the 'e' object also has some additional data that are computed on the server before the Xbasic callback function is called:
| e._currentRowDataOld | A 'dot' variable that contains the data in the fields in the row before
any edits were made to them. For example, if the Grid contains fields, 'firstname',
and 'lastname', then you can reference the data in these fields using
e._curentRowDataOld.firstname, and e._currentRowDataOld.lastname.
If the Grid is not editable then this variable does not have any sub properties.
Note: If the rowNumber parameter is set to 'None' this variable will not contain any sub-properties. |
| e._currentRowDataNew | A 'dot' variable that contains the current data (i.e. edited data) in
the fields in the row. For example, if the Grid contains fields, 'firstname',
and 'lastname', then you can reference the data in these fields using
e._curentRowDataNew.firstname, and e._currentRowDataNew.lastname.
If the Grid is not editable then this variable does not have any sub properties.
Note: If the rowNumber parameter is set to 'None' this variable will not contain any sub-properties. |
| e._currentRowKeys | An array that contains the values for the primary key fields for the
current row. In the case of a .dbf table this is usually the record number.
For example, in the case of a SQL table which has a primary key of 'lastname' and 'firstname', e._currentRowKeys[1] will contain the value of the 'firstname' field in the current row and e._currentRowKeys[2] will contain the vaue of the 'lastname' field in the current row. |
Note: If the handler for your Ajax callback is a URL (as opposed to an Xbasic function), then the 'e' object will not be available to your code.
The function must return the Javascript that you want to execute on the client. For example:
Assume that each row in a Grid has a Div. (You would make a column in the Grid into a freeform edit region to insert the div). The Divs have ids that use the {grid.rownumber} placeholder, which ensures that each div has a unique id. For example:
<div id="R{grid.rownumber}_CONTENT">
So, the div on row 1 would be:
<div id="R1_CONTENT">
Assume that your callback function is called setContent() and it sets the value of the div on the row. Assume also, that the callback function is invoked from a button or event in the Grid row.
In this case, the row number of the row from which the event was invoked will be in e._currentRow (which you could determine by examining the 'Post' tab in Firebug). So the Xbasic function would be:
function setContent as c (e as p)
setContent = "$('R"+e._currentRow+"A').innerHTML =
'"+rand_string(10)+"';"
end function
The 'e' object converts the property assignments to Javascript using the a5GridHelper_generateAutoAjaxResponse() function. If you want to write the Javascript yourself, you can use this function as a great starting point. For example:
e._set.lastname.value = "smith"
e._set.lastname.style = "color: red;"
e._set.lastname.className = "foo"
e._set.firstname.value = "edward"
e._set.firstname.style.color = "red"
e._set.firstname.style.fontSize = "20"
e._setElement.div1.value = "this is a div"
e._setElement.div1.style = "color: red; font-size: 20pt;"
e._setElement.div1.className = "foo"
e._setGridElement.div2.value = "this s a grid element"
e._setRow1.lastname.value = "smith"
e._setRow2.lastname.value = "smith"
e._setRow_1.firstname.style.color = "blue"
e._set.city.style.color = "red"
txt = a5GridHelper_generateAutoAjaxResponse(e,"G","3")
showvar(txt)
The a5GridHelper_generateAutoAjaxResponse() takes 3 arguments: the 'e'
object, the Grid Part ('G', 'D' or 'S' - for Grid, Detail View or Search part)
and a row number.
The popup window will show this Javascript:
{grid.object}._setValue('G','LASTNAME',3,'' + 'smith',true);
$ss('{grid.componentname}.V.R' + 3 + '.LASTNAME','color: red;');
$('{grid.componentname}.V.R' + 3 + '.LASTNAME').className = 'foo';
{grid.object}._setValue('G','FIRSTNAME',3,'' + 'edward',true);
$ss('{grid.componentname}.V.R' + 3 + '.FIRSTNAME',{color: 'red', fontSize:
'20'});
$ss('{grid.componentname}.V.R' + 3 + '.CITY',{color: 'red'});
{grid.object}._setValue('G','LASTNAME',1,'' + 'smith',true);
{grid.object}._setValue('G','LASTNAME',2,'' + 'smith',true);
$ss('{grid.componentname}.V.R' + -1 + '.FIRSTNAME',{color: 'blue'});
$svs('{grid.componentname}.DIV2','thisi s a grid element');;
$svs('DIV1','this is a div');;
$ss('DIV1','color: red; font-size: 20pt;');
$('DIV1').className = 'foo';
It is often necessary to get the Primary Key value(s) for the current row in your Xbasic callback function.
The primary key data is included in the postback variables. The primary key value(s) are stored in an array (because a primary key can be based on multiple columns in the case of SQL tables).
For example, if you did a callback on row 3 for a Grid that was based on a table that has a composite primary key (i.e. a primary key based on more than one column - say PartNumber and OrderNumber), the postback data will include an array called KEYS.R3
Here is how you can write Xbasic to read the data in this variable:
dim arr as p
arr = eval("e.KEYS.R" + e._currentRow)
Now that you have created a local variables called 'arr', you can read the primary key values:
arr[1] - contains the PartNumber
arr[2] - contains the OrderNumber
Alternatively, if your are using an Xbasic function to handle the callback, you can simply use the 'e._currentRowKeys' variable. E.g.
e._currentRowKeys[1] - contains the PartNumber
e._currentRowKeys[2] - contains the OrderNumber
If you have turned on the 'Checkbox' column, the data about which rows were checked is also submitted on the callback. For example, assume that you had checked 3 rows in the Grid. The following data will be submitted on the callback:
checkboxRows.countChecked = 3
checkboxRows.rows[] = 3
checkboxRows.rows[] = 4
checkboxRows.rows[] = 5
checkedRows.key1[] = 00000004
checkedRows.key2[] = 00000005
checkedRows.key3[] = 00000006
The Xbasic function that handles the callback can be contained in an .aex file. You must specify the name of the .aex file in the 'Xbasic .aex files' property.
If you use Action Javascript to write the Ajax call function for you, you will notice that the Genie has a prompt that allows you to specify if data from the current row should be submitted when the callback takes place. If the row is a read-only row however, then data from the current row will not be submitted (even though the checkbox to submit data has been checked). The primary key values for the current row will however be submitted.
If you need to data from the current row in order to execute your callback function, you can instruct Alpha Five to use the primary key values that were submitted to get data for the current row. Alpha Five will do a query to find the record with the specified primary key and it will populate variables with the same name (e.g. V.R1.LASTNAME) as if the variables had been submitted from the browser.
In order to enable this feature, you must include this name/value pair in the OtherData parameter:
_getData=true
The function or URL that handles the Ajax callback typically will send some Javascript code back to the Browser. This Javascript code can set properties of the Grid (e.g. set the value of a field to 'Paid', or set the color of a field to red).
More correctly stated, the Ajax callback can return Javascript to set any DOM (Document Object Model) property in the Browser.
As an alternative to generating Javascript code in your callback handler to set Grid properties, you can set properties of the special e._set object in your event handler function. Alpha Five will then automatically generate the appropriate Javascript.
For example, assume that the current row in the Grid contains a field called 'OrderTotal' and 'ShippingCharges'. You want to make a callback to the server, submitting the current value of 'OrderTotal', then compute the 'ShippingCharges' on the server and in your Ajax response, you would like to set the value of the 'ShippingCharges' field to the value that you computed on the server.
Here is what your Xbasic function might look like:
function computeShipping as c (e as p)
dim orderTotal as N
'get data from the e._currentRowDataNew object and convert it to numeric.
orderTotal = val(e._currentRowDataNew.orderTotal)
dim shippingCharges as N
'execute code to compute the shipping charges.
'dim formattedShippingCharge as c
'execute code to format the shipping charges with currency symbol, etc.
dim ajaxResponse as c
'The ajax response will call the Grid object's .setValue() method. e._currentRow is the row number of the row that was submitted.
ajaxResponse = "{grid.object}.setValue('G','SHIPPINGCHARGES'," + e._currentRow + ",'" + js_escape(formattedShippingCharges) + "');"
computeShipping = ajaxResponse
end function
Clearly, the Javascript response that this function computes is non-trivial. Here is how this function can be greatly simplified by using the e._set object:
function computeShipping as c (e as p)
dim orderTotal as N
'get data from the e._currentRowDataNew object and convert it to numeric.
orderTotal = val(e._currentRowDataNew.orderTotal)
dim shippingCharges as N
'execute code to compute the shipping charges.
'dim formattedShippingCharge as c
'execute code to format the shipping charges with currency symbol, etc.
e._set.shippingCharges.value = formattedShippingCharge
'if the shipping charges are above 100, set the font color to red.
if shippingCharges > 100 then
e._set.shippingCharges.style.color = "red"
end if
end function
Note that now the function does not return any Javascript (although of course it could if you wanted it to). After the callback function has executed, Alpha Five examines the e._set object and it automatically generates the appropriate Javascript to set the properties that you specified in the e._set object. This computed Javascript is automatically appended to the Javascript response computed by your callback function.
You can set the following properties in the e._set object:
| e._set.fieldname.value | Sets the value of a field in the current row of the Grid. E.g.
e._set.lastname.value = js_escape("O'Hara")
Note: The value that you set must be processed by the js_escape() function to encode special characters, or else you will get a Javascript error. |
| e._set.fieldname.style | Sets the style of a field in the current row. Style is a comple CSS
string. Any existing style that has been applied to the field will be
overwritten. E.g.
e._set.style.lastname.style = "color: red; font-size: 12pt"
|
| e._set.fieldname.style.styleAttribute | Sets an individual style attribute of a field in the current row. The
existing style is preserved and only the specified styleAttribute is
overwritten. E.g.
e._set.style.lastname.fontSize = "20pt"
Note: The styleAttribute is case-sensitive.
Contrast setting individual styleAttributes, with the previous command that sets the entire style CSS value in a single command. |
| e._set.fieldame.className | Sets the class name of a field in the current row. |
You can also set properties of other rows in the Grid (other than the current row) by using the special 'e._setRow<rowNumber>' object.
Where <rowNumber> is the row number of the row. In the case of new record rows, use and underscore in front of the row number.
For example:
e._setRow3.lastname.value = "Smit"
e._setRow_1.lastname.style.color = "Green"
In some cases, you will want your Ajax callback to set properties of an object that is not in the current Grid row. For example you might have an element (e.g. a DIV or SPAN in a free-form edit region above the Grid).
It recommended practice to include the Grid alias in the name of the Id that you give to these elements so that if you have a page that contains more than one Grid component on it, the Ids of these elements are unique.
For example, in a free-form section of a Grid, when you defined the element, you might have entered:
<div id="{grid.componentname}.DIV1"></div>
rather than simply:
<div id="DIV1"></div>
At run-time, the {grid.componentname} placeholder would be replaced by the Grid's unique alias. So, if the Grid alias was 'GRID1', the actual Id of the DIV would be 'GRID1.DIV1'.
Any element that is named using the '{grid.componentname}.name' convention is called a 'Grid Element' (as opposed to simply an 'Element').
You can set the .value, .style and .className properties of Grid elements in the same way that you set the properties of fields in the current row. The only difference is that you use the e._setGridElement object.
For example, say that you have a Grid element named '{grid.componentname}.DIV1' and you want to set its 'value' and 'style' ('value' in this case would actually be the innerHTML property). You would use this command:
e._setGridElement.DIV1.value = js_escape("This is the contents of the div")
e._setGridElement.DIV1.style.color = "red"
Al 'Element' is essentially the same as a 'Grid Element' except that it does not include the '{Grid.componentname}' placeholder in the Id. You can use the e._setElement object to set properties of 'Elements'.
For example, a free-form section of the Grid might have this element:
<div id="ELEMENT1"></div>
You could execute this command to set properties of this element:
e._setElement.ELEMENT1.value = js_escape("This is the contents of element1")
Linked Content Sections allow you to display linked data in your Grid.
The linked content is displayed in a Tab or Accordion control if the Linked Content Section links more than one object. Linked Content Sections essentially duplicate the functionality of the Tabbed Grid Linker component and the Grid Linker component (from V9 and prior version). But because Linked Content Sections use Ajax, they don't have the performance penalty that Tabbed Grid Linkers and Grid Linkers have. You can place as many Linked Content Sections on your Grid as you want. For example, you might have a Customer Grid with a Linked Content Section below the Grid that displays an Orders Grid (showing orders for the selected Customer) and a Payments Grid (showing payments received from the selected Customer). These two Grids would be displayed in a Tab or Accordion control. Then, you might have another Grid (displayed, say, to the right of the Customer Grid) showing a list of all documents/letters/proposals, etc. that have been sent to the selected customer. NOTE: At present, you can only place Grids in Linked Content Sections. We will add .a5w pages and other web pages in the future.
The image below shows the Customer Grid with a Linked Content Section showing the Orders Grid. This Grid, in-turn, has its own Linked Content Section which shows the Order Details Grid.
To place Lined Content into the Grid, check the 'Has linked Grids or other content' checkbox and then click on the smart field. The following dialog is displayed.
You can add add many Linked Content sections as you want.

Click the 'Add Linked Content Section' button and give the section any arbitrary name that you want.

Then, click the 'Define Linked Content' button to define the linked content.

After you have defined the linked content, you must then specify where on the Grid the linked content should appear. You do this by placing a special placeholder in one of the Grid's freeform edit regions.
To place the linked content, click the 'Edit Freeform Edit Region' button and select which freeform edit region you want to use.
Then, insert the placeholder into the freeform html.

When you are designing a Grid (Grid part), the 'Insert...' menu now has a new command. In addition to the usual objects (such as Tabs, Containers, Frames, Images, Buttons, etc.), there is now a new object that you can insert into the Grid - 'Linked Grid(s)'. If you specify more than one Grid, the linked grids will display in a tab or accordion control. The linked Grids are linked to one or more fields in the current row.
The image below shows a Customer grid. The last cell in the Grid contains an embedded, linked Grid showing the orders for that customer.
The embedded Grids are rendered by making subsequent Ajax callbacks after the parent Grid has rendered. This means that the embedded Grids do not slow down the initial rendering of the parent Grid.
Property name: 'Highlight row on hover' ('Properties' pane)
It is sometimes difficult to immediately find the position of the cursor on a grid. Selecting this property will cause the style of a row to change when the mouse hovers over the row. This helps identify the current row that will be selected with a mouse click or double-click.
![]() |
The row where the cursor is positioned is highlighted |
Property name: 'Has 'Records Per Page' selector' ('Properties' pane)
The number of rows to show on the grid when it first displays is set in the grid properties. Adding the 'Records Per Page' selector allows the user to change the number of rows displayed after the grid opens on a page. The selector is shown at the bottom of the page and has a dropdown list with the values specified in the 'Records Per Page' selector choices. When the user selects a new value, the grid refreshes and show the number of rows selected. This option allows the grid to initially open with a limited number of rows to take less space on a page, and still allow the user to decide how many rows they wish to view.
The Records Per Page selector |
Property name: Query-by-Example row' ('Properties' pane)
Previously, the only way to find specific records was to use a search section or 'quick search'.
Now there is a new method to search individual columns using a sophisticated 'query by example' process. A link is shown at the bottom of the grid to show or hide a query row. The initial display of the row can be shown or hidden. Clicking the link either shows or hides the Query-by-Example row. It has a textbox for each row to allow the user to enter some search text. The user then clicks on the icon to the right of the textbox and a list of possible search criteria opens. The user can clear all filters on all columns, remove the filter on the current column with 'No filter'., or select specific criteria for the current row. The query runs as soon as the criteria is clicked. Additional queries can be run on other rows to further filter the data.
Link to Show / Hide Query by example |
![]() |
Grid showing Query By Example row |
![]() |
Query by example search criteria |
![]() |
Grid filtered on 2 columns queried with 'Starts with..' |
Property name: 'Detail View window position' ('Detail View-> Properties' pane)
There are new options for where the Detail View is shown. It can be shown in page (the same as previously), in the grid, in a popup modal window, or in a popup modeless window. The modal popup window will gray out the underlying grid and nothing on the grid can be selected. The modeless popup allows selecting records on the grid with the popup open. The popup windows have a 'drag' capability to allow them to be moved around on the page.
The Detail View includes a toolbar that allows you to navigate from record to record. When in enter mode, has a 'Save and Enter' button (Ctrl-F9)
Detail views can now be defined for 'Form' and 'Stacked' layouts. (Previously Detail View was only available for 'Grid' layout)
![]() |
Detail view on page |
![]() |
Detail View in modal popup window |
![]() |
Detail View in grid |
![]() |
Detail View on columnar grid with modeless popup window |
Property name: 'Has row expander' ('Properties' pane)
The row expander is another method to show information related to a record on a row. A column is added with a 'plus'
icon that can be selected to 'expand the row'. A minus
icon will be shown after the row is expanded that can be selected to close the expanded row. There are 2 row expander types.
The 'LinkedGrids' option allows selecting one or more grid components that can be linked to the current record in the row. The linked grids can be shown in tabs, or an accordion control.
The 'CustomEvent' will cause the grid event 'OnExpandRow' to fire. This event sets a number of properties such as e.html and e.javascript. The contents of the expanded row will be set to e.html. If the e.javascript is not null, the javascript contained in this property will be executed. There are other optional properties available to allow a developer to create a custom display that can be linked to the current record.
Multiple records can have their row expanded, allowing the user to view additional information about multiple records.
If the 'Mode' property is set to 'Single', then only one row can be expanded at a time. If a row is expanded and you expand another row, the currently expanded row will be collapsed.
![]() |
Selecting the row expander icon to open the expanded section |
![]() |
Expanded row with 2 grids in a tabbed control with the tabs on top. |
![]() |
CustomEvent selected using the example code in the 'OnExpandRow' event |
Property name: 'Use a master layout template' ('Grid Properties' pane)
Using a template allows you to layout the different parts of the Grid in the component definition, rather than on the page. Several different template styles are available, such as tabs and accordions. The Detail View includes a toolbar that allows you to navigate from record to record. The text on the tabs or labels can be specified, and the initial pane to show can be specified.
![]() |
Grid in a master template layout with a Tab Container with tabs on top |
![]() |
Detail view in a master template layout with a Tab Container with tabs on top |
Property name: 'Can collapse grid?' ('Grid Properties' pane)
A feature has been added allow a user to click a minus icon
to 'collapse' a grid to hide it and just show a simple title bar. The title bar has a plus icon
to reopen the grid. This is similar to an accordion control and requires the grid to be placed in a master template.
![]() |
Collapsible grid expanded with a grid in an accordion master template |
Title bar with grid collapsed |
Property name: 'Lookup' ('Fields->Field Properties' pane)
A lookup defined for a field now opens in an Ajax window instead of a popup window. This provides a number of improvements.
The lookup opens must faster
Opens the lookup in a window on the page, not in a new Browser window. This means popup blockers can't prevent the lookup from opening and the user can't leave them open.
The lookups can easily have dynamic and static filters applied. A dynamic filter will base the lookup on data already entered into the Grid (e.g. enter state of 'ma' - when you open the lookup only customers in 'ma' are shown)
The lookup can be configured to force a user to select from the lookup and not allow them to type in a value in the field with the lookup.
![]() |
Lookup opened with dynamic filter on state |
Property name: 'Has checkbox select column' ('grid Properties' pane)
Selecting this option adds a column with a checkbox for each row to select one of more records, with a select / deselect all option. This feature is meant to be used in conjunction with custom Ajax callbacks (described elsewhere in this document).
![]() |
Checkbox select column with all selected |
Property name: 'Row edit style' ('Update Settings' pane)
A updateable grid can open with all rows in edit mode by selecting the 'AllRows' option. Selecting the 'RowOnDemand' option will open the grid in view mode. The row can be placed into edit mode either by clicking the 'Edit row' icon, or by double clicking on a field. If you double click on a field, initial focus will be on the field.
A related option is the 'One edit row at a time' property. If this is checked, it will allow only one row at a time to be in edit mode. Multiple rows can be placed in edit mode if this is not selected.
![]() |
RowOnDemand with one edit row not selected. Two rows are in edit mode and a change has been made in the first row. |
Property name: 'Lazy edits' ('Update Settings' pane)
The option for 'Lazy edits' is only displayed if the row edit style is 'RowOnDemand'
If 'Lazy edit' is selected, the database will not be queried to get current data when you put a row into edit mode. This makes it quicker to switch to edit mode. If it is not selected, the row will be refreshed when placed in edit mode to get the current data.
Property name: 'Refresh data on row dirty' ('Update Settings' pane)
This option only applies if the row edit style is 'AllRows'
When this option is selected and a user begins editing in a row, a callback is executed to get the current data.
Property name: 'Allow individual rows to be saved' ('Update Settings' pane)
This option is only shown if the row edit style is 'AllRows' and allows saving an individual record instead of submitting all rows after an edit.
When it is selected, a 'Row Status' column is displayed. This column shows icons that allow you to perform actions specific to the row, such as 'Save Row', or 'Undo changes in row'.
Property name: 'Row refresh method after edits' ('Update Settings' pane)
Previously you had to commit all edited rows at once. This option allows setting how the data in the Grid should be refreshed after data is updated, deleted or inserted.
'AutoSelect' - let Alpha Five choose a method
'FullPage' - refresh all records in the Grid (slowest, but guarantees that all summary fields and linked records are refreshed)
'SingleRow' - only refreshes data in the edited row
'Minimal' - fastest method, but will not update summary fields
If you redirect to another page after a successful update, then you must turn off updates to individual rows.
Property name: 'Error style name' ('Properties' pane)
Previously errors where shown on their section on a page. Now they are shown in the Grid itself.
The error style property determines how the error messages are displayed.
'block' - under the field
'inline' - next to the field
'tip' - popup error when hovering over the field
'icon' - display an error icon and show error when hovering over icon
'global' - display all errors in a single location
Property name: 'New records edit style' ('Update Settings' pane)
This has two options
AlwaysShown - A row for entering a new record is always show for an updateable grid.
![]() |
ShowOnDemand - A link replaces the edit row to allow showing or hiding the new record row on demand.
![]() |
Property name: 'Conditional Style' ('Grid->Fields->Field Properties' pane)
Previously, the only way to change the look of a field based on a condition was to use a custom control. This option allows changing the CSS style class of a control based on a conditional expression. The style can be an inline style or a CSS style class name. The CSS styles can be loaded from an external CSS file.
Property name: 'Local CSS definitions' ('Properties' pane)
This provides the ability to define additional CSS classes that can be used in the Grid.
Property name: 'CSS Linked files' ('Properties' pane)
This provides the ability to specify additional CSS files that should be linked on the page.
Property name: 'Additional Grid styles' ('Properties' pane)
This provides the ability to list additional Alpha Five styles to be included on the page. A comma delimited list of style names can be added.
Property name: 'Insert Layout Command...' (Grid->Fields' pane)
The layout commands for 'stacked' layouts like columnar have a number of new features.
Modern style tabs
Frames - classic and modern. Modern frames can have collapse/expand button
Containers - A section inside of another section that can have its own formatting
![]() |
Modern style tabs, modern frame with collapse/expand and city state zip fields in a container. |
There are a number of 'unbound' controls available in the Layout Controls section.
Static image (can be conditional based on data in the grid. Can also be based on comparisons with summary values)
Static text
![]() |
Image based on a value in the grid and unbound text |
The Ajax grid includes some built-in keyboard shortcuts
Up and Down arrow change row with focus.
F9 commits changes
F2 - open the lookup grid if focus is in a control that is defined as a lookup.
Ctrl-F9 - Save current record and enter a new record (in Detail View)
You can now specify that the link address type is 'Javascript'. Any Javascript function call or command can be added to the 'onclick' event. The Javascript will be executed when the link is clicked.
![]() |
JavaScript link with onclick event opening an 'alert' box |
Property name: 'JavaScript' ('Grid Properties->Javascript - Row Events' and 'Grid Fields->Field properties->Javascript' panes)
Define Javascript event handlers at the control level and the row level. The Javascript can make an arbitrary ajax callback to validate data, obtain new data, populate a select box, etc. This provides the capability to create cascading lookups.
Common uses:
Define an 'onChange' event for a textbox control.
Define an 'onDblClick' event for when a user double clicks on a row in the grid.
Define an 'onSelect' event for a dropdown control to execute an Ajax callback to populate another control such as another dropdown.
Define client side validation to execute when the user leaves a control by using the 'onBlur' event.
Define an event to make an Ajax callback to populate other fields based on an entered field value, such as filling in City and State after a zip code has been entered and the user leaves the field.
![]() |
Javascript events supported for fields |
Property name: 'JavaScript function declarations' ('Grid Properties' pane)
This property allows allow you to define Javascript functions that can be called from Javascript events. These functions will be added to the page header and must contain valid Javascript syntax.
![]() |
An example JavaScript function definition. |
Property name: 'Javascript Linked files' ('Grid Properties' pane)
Additional Javascript files can be linked to the page. The files can contain JavaScript functions used by event handlers on fields or rows or other client side actions.
Property name: 'Xbasic function declarations' ('Grid Properties' pane)
Allow you to define Xbasic functions that can be called from Xbasic event handlers. These functions are called by server side actions defined in the grid 'Events'.
Property name: 'Validation Xbasic' ('Grid Fields->Field Properties' pane)
You can now write your own Xbasic code to validate fields. This validation code runs on the server when a record is submitted.
If you have a Grid based on an AlphaDAO data source, and you have 'Check for write conflicts' turned on, you can turn off write conflict checking at the individual field level. This was added because certain field types (e.g. the 'ntext' type in SQL Server) cannot be used in a WHERE clause with an = operator - which is what is required in order to use a field in a write conflict check.
Now, when you select certain fields in the Grid, if their data type precludes them from being used in a WHERE clause with an = operator, they are automatically excluded from the list of fields for which write conflicts will be checked.
Property name 'New record rows position' ('Update Settings' pane)
You can now specify if the empty rows, used to add new records to an editable grid, should be positioned above, or below the existing records. Previously, the new record rows were always shown below the existing records.

Grid showing new record rows positioned above existing rows.
In previous versions, the Detail View was opened by clicking on a hyperlink field in the Grid. Now, you can set the method for opening the Detail View. The options are:
If you choose method 2 or 3, there is no need to set the style of one of the Grid columns to a hyperlink. If you choose the first method and you do not define the hyperlink field, Alpha Five will automatically set the first non-hidden field to be the hyperlink (previously it gave an error and forced you to choose a field) .
You can customize the icons and bubble help that are displayed in the Detail View toolbar. To bring up the customization dialog, click the smart field in the 'Customize the toolbar icons' property. For some of the icons, you can specify the disabled icon as well.
![]()
You can customize the messages and icons used in the the Javascript dialogs. For example, the Delete Record confirmation dialog shown below has been customized:

To customize the Javascript dialogs, click the smart field for the 'Javascript windows' prompt in the 'Customization' section in the Grid Properties pane.

You can now more easily deal with situations where the date format that a user wants to use is different than Regional Settings date format for your server. For example, assume that your server is on a machine in the US where the date format is 'MM/dd/yy'. Your users in the US who want to see and enter dates using the 'MM/dd/yy' format. However, your users in the rest of the world want to use the 'dd/MM/yy' format to display and enter date values.
This is now easily accomplished.
1. There is a new property called 'Date Format' in the 'Miscellaneous' section on the 'Grid Properties' pane. The default for this property is 'MM/dd/yy', but you can select a different value. You can override this property at runtime in Override Settings by setting the clientSideDateFormat property. For example
tmpl.clientSideDateFormat = "dd/MM/yy"
You can also override this property at runtime by setting the special session.__protected__clientSideDateFormat variable. This is the more likely scenario as you can set this variable for each user when they log into your application.
2. When you configure the date picker for date and time fields, you will notice that the default value for the 'Format' property has been changed from "mm/dd/yy" to "<Default>". This indicates that the date picker format will be inherited from the global date format (set by the clientSideDateFormat property discussed above).
3. When you select a date or time field in the Grid or Detail View part, a default format is defined. The format is:
time("{grid.clientSideDateFormat}",<value>)
{grid.clientSideDateFormat} is a special placeholder that gets replaced at runtime with the value of the Grid's clientSideDateFormat property.
Assume that User1 logs on from New York. When User1 logs on, you set the special session.__protected__clientSideDateFormat variable to "MM/dd/yy". All dates in the Grid will appear in the MM/dd/yy format. When the user makes a selection from the Date Picker, the date will be entered in the MM/dd/yy format.
Assume that User2 logs on from London. When User2 logs on, you set the special session.__protected__clientSideDateFormat variable to "dd/MM/yy". All dates in the Grid will appear in the dd/MM/yy format. When the user makes a selection from the Date Picker, the date will be entered in the dd/MM/yy format.
When User1 or User2 submits data to the server, the date values are automatically converted to the format required by the Regional Settings of the machine on which the server is running.
This will all happen seamlessly, without requiring you to make any modifications to your Grid component.
As a result of this change, the old 'Date format on server does not match client' property in the Grid has been removed.
Note: If you are outside the US, you will probably want to change the default value for the Date Format to 'dd/MM/yy' for each new Grid that you build.
You can now define several 'client-side' properties for a Grid. These are:
Client-side calculated fields are computed using Javascript. The calculation is performed as soon as any of the operands in the calculated expression are changed.
Warning: If you have defined a formatting expression for a field that also has a client-side calculation, the formatting expression will be overwritten by the result of the client-side calculation. You must therefore put the the formatting logic into your client-side calculated expression.
Any field, or Container can by dynamically shown/hidden. If you want to show/hide multiple fields at once, wrap the fields in a Container control (Form layout mode) and set the show/hide expression for the container.
You can enable/disable an input control.
You can define conditional styles. The conditions are evaluated in the Browser using Javascript. This is an extremely powerful feature as it allows you to dynamically style controls without having to make Ajax callbacks. For example, if a user types in a value into a Quantity field that is too large, you can immediately display the field in red. Contrast 'client-side' conditional styles with 'server-side' conditional styles (also supported). With 'server-side' conditional styles, the conditions are expressed using Xbasic expressions and the conditions are evaluated on the server.
You can define masks for character fields. For example, a US Phone number: ( ) -
For numeric fields, you can define number formats.

The client-side Calculated fields, Show/hide fields, Enable expressions and Conditional styles are all implemented using 'watch' events. For example, if you examine the source in the Browser for a page the defines a calculated field for 'extendedtotal' using the expression 'round(price * quantity,2)', you will see the following Watch event has been defined automatically:
GRID1_GridObj._gridRowWatches['CALC_G_EXTENSION'] = {
watch: ['PRICE','QUANTITY'],
onChange: function(data) {
var PRICE = $u.s.toNum($gvs('GRID1.V.R' + data.rowNumber + '.PRICE'));
var QUANTITY = $u.s.toNum($gvs('GRID1.V.R' + data.rowNumber + '.QUANTITY'));
GRID1_GridObj._setValue('G','EXTENSION',data.rowNumber,'' + $u.n.round((PRICE*QUANTITY),2));
}
}
The above Javascript adds a new watch event (called 'CALC_G_EXTENSION'). It watches the PRICE and QUANTITY fields. The onChange event gets passed an object called 'data' that has the rowNumber of the row in which the change takes place. It then gets to local variables, PRICE and QUANTITY which are the values in the corresponding controls in the Grid part. Finally, it uses the ._setValue() method to set the value of the EXTENSION field to the result of the expression.
You can define your own custom Watch events if the automatically generated watch events (defined when you create a client-side calculated field, etc.) do not do exactly what you want. In most cases you should not need to use custom Watch events, but for power users, its nice to have this capability. You can define Custom Watch events for the Search part, Grid part and Detail View part. Go to the 'Javascript- Other' section in the appropriate properties page and click the builder for 'Watch events'.
You can create as many watch events as you want. For each watch event, you specify a unique (arbitrary) name to identify the event, the names of the fields you want to watch and the javascript to execute when the value in any of the watched fields is changed.
When you define the watch event, you can (optionally) use special 'helper' functions to simplify your javascript. For example the helper function *$('quantity') expands to:
$gvs('GRID1.V.R' + data.rowNumber + '.QUANTITY').
The above example Watch event could be written using 'helper' functions as follows:
GRID1_GridObj._gridRowWatches['CALC_G_EXTENSION'] = {
watch: ['PRICE','QUANTITY'],
onChange: function(data) {
var PRICE = *gvn('PRICE');
var QUANTITY = *gvn('QUANTITY');
*svs('Extension',$u.n.round((PRICE*QUANTITY),2));
}
}
(Note: 'Helper' functions can only be used when you create custom watch events. The 'helper' functions all start with * and are documented in the Watch Event builder.)
The generic Javascript Watch events make it very easy to dynamically set a control's label at run-time.
For example, say that your Grid has a field called 'COUNTRY'. If the value in COUNTRY is 'USA', you want to set the label on the ZIP field to 'Zip code', otherwise you want to set it to 'Postal Code'.
NOTE: This example assumes that the Grid is set to display data in Form mode.
Here is how you would do it:
var COMPANY = *gv('COMPANY');
var labelValue = 'Zip code';
if( COMPANY != 'USA') labelValue = 'Postal Code';
$('{grid.componentname}.LBL.R' + data.rowNumber + '.'+'ZIP'+'').innerHTML =
labelValue;
If you have built Grids on .dbf files in V9 and earlier, a major deficiency has been that the Grid did not honor most Field Rules. That meant that you had to code validation rules manually to mimic the rules you had defined in Field Rules.
Now, rules defined in Field Rules are automatically enforced in the Grid. You do not need to manually add any validation logic to your Grid.
You can tag any text in the Grid definition so that it becomes replaceable, depending on the selected language.
To tag text, you enclose it in <a5:r> and </a5:r> tags. For example, you might tag the heading for the Lastname column as:
<a5:r>Lastname</a5:r>
To open the Language Definition dialog see the 'Language Definitions' property in the 'Miscellaneous' section of the 'Properties' pane.
You can define as many language definitions as you want.
Each language definition is a set of name=value pairs (values must not include line breaks). For example, assume you tagged the following strings in your Grid definition:
<a5:r>First Name</a5:r>
<a5:r>Last Name</a5:r>
<a5:r>City</a5:r>
Your language definition for the <Default> language might be:
First Name=First Name
Last Name=Last Name
City=City
The language definition for French might be:
First Name=Prénom
Last Name=Nom de Famille
City=Ville
You can use expressions in the replacement strings by prefixing the expression with 'expn;'. For example, the language definition below uses expression that reference a session variable and a variables that might have been defined in the OnGridInitialize event.
First Name=Prénom
Last Name=Nom de Famille
City=Ville
Company=expn:session.companyName
WelcomeMessage=expn:rtc._myvariables.welcomeMessage
If you don't specify an active language, the <Default> language is assumed. To set the active language, you set the 'ActiveLanguage' property. You can set this property in the 'Override Settings' section in the .A5W page that loads the Grid, or in the Grid component's OnGridInitialize event.
For example, to set the ActiveLanguage in the OnGridInitialize event:
e.tmpl.ActiveLanguage = "French"
A second way to set the active language is by using the special protected session variable, session.__protected__activeLanguage. For example:
session.__protected__activeLanguage = "French"
If you set both the session.__protected__activeLanguage and the 'ActiveLanguage' property in Override Settings or OnGridInitialize, the session.__protected__activeLanguage property is honored.
You can pass in an external language definition to the Grid at run-time by setting the 'languageDefinition' property in Override Settings or the OnGridInitialize event. If you pass in an external language definition which defines a replacement value that is also defined in the language definition that is defined in the Grid itself, the external language definition will be used.
The example below shows how to define an external language definition. Note that 'Surname' and 'Postal Code' are literal values and =date() is an Xbasic expression.
tmpl.languageDefinition = <<%txt%
<a5:r>lastname</a5:r>="Surname"
<a5:r>zip</a5:r>="Postal Code"
<a5:r>date</a5:r>=date()
%txt%
If you have defined a lot of Xbasic event handlers in your Grid components, it might make sense to move the bulk of the Xbasic code outside the Grid component and into global Functions (defined in the Code tab of the main Control Panel).
You can then compile your functions into an .AEX file and add a reference in your Grid component to the .AEX files that it needs to link in.
Note: To create an .AEX file with your Global Functions, simply right click on white space in the Code tab of the main Control Panel).
Note: Functions that are defined in .AEX file can be used in event handlers in the Grid. They cannot be used in calculated field definitions. (Calculated fields are only available for Grids based on .dbf. For Grids based on SQL, the 'calculated' fields are defined in the SQL Select statement).
The Grid has always allowed you to customize the layout of the record navigator, but now, you can customize the entire Grid Toolbar and you can add your own custom buttons to perform actions that you define.
For example, this image shows how we have added 3 custom buttons to the toolbar.

To customize the toolbar, click the smart field for the 'Customize Grid toolbar template' property.

The Genie lets you customize the toolbar for when the Grid is read-only and when it is editable. You can make modifications to the HTML template. The placeholders in curly brackets are used for the different parts of the toolbar.
To get started, click the hyperlink to insert the default template.

When doing a Live Preview from the Grid, Page Layout, and Tabbed UI builder, you can use any installed browser. You are not limited to your default browser.

You can now insert group headings in the data displayed in a Dropdown control. For example:

The above list was entered into the choices for the Dropdown control as follows:
[[[General Motors]]]
Camaro
Cadilac
GMC
[[[Ford]]]
Mustang
Lincoln
Focus
[[[BMW]]]
3 Series
5 Series
7 Series
The editor for freeform regions has been changed slightly. Now, you can insert placeholders for the controls in your grid (e.g. {lastname}) or for the data that is in the control (e.g. {data.lastname}).
If you have used a freeform edit region in a Grid created in V9 or earlier, you might need to change some of your placeholders to use the 'data.' prefix.
The reason is as follows:
In V10, a label control is now automatically wrapped in a span tag. In V9 and earlier, a label control was not wrapped in a span, and so the {lastname} placeholder, for example, would have been replaced with 'Smith'. But in V10, this placeholder will be replaced with '<span>Smith</span>
If your component was not expecting the <span> to be in the replacement value, it might break your component. Changing the placeholder to use the 'data.' prefix will get you back to the V9 behavior.
In the example shown below, if the {lastname} placeholder had been used, the image name would not have resolved correctly.

The number of server-side system events that the Grid exposes has been substantially expanded.
The full list of server-side system events is shown below:
The new OnSearchPartFilterCompute function allows you to create a customized Search Part where you (and not Alpha Five) are responsible for converting the data submitted by the Search Part into a search filter.
This event allows you to modify the search part filter before it is executed. You can take the data submitted when the user clicks the Search Button on the Search Part and compute your own filter expression, rather than allowing Alpha Five to compute the grid filter.
The 'e' object that is passed into the event handler includes these properties:
e.rtc.Filter_SearchPart -- filter computed from
submitted data in the Search Part
e.rtc.Parameters_SearchPart -- parameter values for arguments in the
filter.
e.SearchDataSubmitted -- Search data submitted
You can modify this. So, for example, in the event handler you might execute this code:
e.rtc.filter_searchPart = "lastname = \"smith\""
Now, when search is executed, it will search for records with lastname = "smith", regardless of what the user entered into the Search Part.
This feature is often used in conjunction with putting variables into the Search Part form.
To put a variable into the Search Part, set one of the search fields to be a 'freeform edit region' and then enter HTML similar to this (this example if for a variable called 'myvar1'):
<input id="{grid.componentname}.S.MYVAR1" size="40" maxlength="200" class="GlassOliveInput" type="text" name="S.MYVAR1" value="" />
In your event handler, you can refer to this value in Myvar1 as
e.SearchDataSubmitted.myvar1
The Grid Object exposes a very rich system of client-side events that you can use to customize the Grid behavior. Event handlers for client-side system events are coded using Javascript.
Below is a list of client-side events that are exposed to the developer:
In order to define a client-side event expand the 'Javascript - System Events' property and then click on the smart field.

The Client-side Grid System Events dialog is opened. It shows all of the possible events and gives a short description of each event. If the event makes any data available to the executing Javascript code, the 'Parameters' section shows the names of the parameters.
You can use the 'Filter' box to filter the list of events to help you find the event you are looking for. You can also use the 'Defined events only' checkbox to quickly find the events for which you have defined code.

When you write the Javascript event handlers, you might want to use certain placeholders in your Javascript. These placeholders get replaced by actual values when the Grid is rendered.
For example, the {Grid.componentName} placeholder gets replaced with the actual Grid alias at run-time.
To insert a placeholder in your code, click the 'Insert placeholder...' hyperlink.
You Javascript code can call any of the methods that the Grid object exposes. To see a list of the methods, click the 'Insert Grid method...' placeholder.
Say you wanted to put up a dialog that said 'Searching. Please wait..' while your Grid component was performing a search. As soon as the search completed, you want to remove the message.
To do this you would add code to the 'canSearchSubmit' event to show the message.
A5.msgBox.show('Searching...','<div style=\'padding: 20px;\'>Please wait while we search for the records.</div>','none',function() {});
Then in the 'afterSearchSubmit' event, you would clear the message.
A5.msgBox.hide();
The Grid component now implements many of the same keyboard shortcuts used in Alpha Five desktop forms. These are:
| Up | Move focus to the previous row in the Grid part |
| Down | Move focus to the next row in the Grid part |
| F9 | Save the current record |
| Shift+F9 | Save all of the records (in a Grid that allows multiple records to be edited at once) |
| Ctrl+F9 | In the Detail View - save the current record and start entering a new record. |
| Enter | Puts the field with focus into edit mode |
| Page Up | Moves to the previous page of records |
| Page Down | Moves to the next page of records |
| Ctrl+D | Delete current record |
| F2 | Open the lookup window for the current field. |
| Esc | Abandon edits made to the current field. |
The way in which an .a5w page that runs components is constructed has been changed in V10.
In V9, if you examine an .a5w page after you have inserted a component into the page, you will see an Xbasic code block that looks similar to this
with tmpl
componentname = "GRID1"
end with
The Xbasic between the opening 'with tmpl' and the closing 'end with' could be used to override any of the Grid settings. So for example, if you wanted to change the Grid style to a value that was set by a session variable called session.style, you would have:
with tmpl
componentname = "GRID1"
style_name = session.style
end with
In V10, when you place a component on a page, the Xbasic code block in the .a5w page where you override settings is slightly different. It now looks like this:
tmpl.override_settings = <<%override_settings%
componentname = "GRID1"
style_name = session.style
%override_settings%
a5w_resolveVariablesInOverrideSettings(tmpl,session,local_variables())
The a5w_resolveVariablesInOverrideSettings() function resolves page and session variables in the override_settings string. So, after this function has been executed, the tmpl.override_settings property will contain this value (assuming that session.style has a value of 'Airport':
tmpl.override_settings = <<%override_settings%
componentname = "GRID1"
style_name = "Airport"
%override_settings%
When you publish an existing .a5w page (created in V9), the Xbasic in the .a5w code is automatically converted to the new V10 pattern.
The reason that is was necessary to change the code pattern is that with the code pattern used in V9 and earlier, there is way to know exactly which properties where changed in the override settings section of the code. This was not a problem in V9 and earlier as there was no need to know which properties had been overridden.
However, in an Ajax Grid, it is essential that we know which properties have been overridden so that this information can be stored in a hidden field in the Grid. This is necessary because after the Grid has been displayed initially, all further callbacks are not handled by the original .a5w page (that contains the override settings code), but are handled by a special page called __a5RunGrid.a5w (which is published automatically every time you publish any component).
Since the Ajax callbacks are processed using __a5RunGrid.a5w, (which is a generic page with no override settings code in it), the override settings are read from the hidden field in the Grid.
If you want to refer to local variables in the override_settings string, you must prefix the local variable with 'pageVar' and you must put the local variable in the special 'pageVar' variable frame.
For example:
dim rows as n
rows = 23
dim pageVars as p
pageVars.rows = rows
tmpl.override_settings = <<%override_settings%
componentname = "GRID1"
style_name = session.style
rows = pageVars.rows
%override_settings%
a5w_resolveVariablesInOverrideSettings(tmpl,session,local_variables())
In an Ajax Grid, there is a precise naming convention used for form fields.
The ID of a field object in the Grid part is:
{Grid.ComponentName}.V.R{Grid.RowNumber}.FIELDNAME
Examples:
GRID1.V.R3.LASTNAME
MYGRID.V.R-2.FIRSTNAME
The ID of a field object in the Detail View part is:
{Grid.ComponentName}.D.V.R{Grid.RowNumber}.FIELDNAME
Examples:
GRID1.D.V.R1.LASTNAME
MYGRID.D.V.R-1.FIRSTNAME
The Name of a field object for both Grid part and Detail View part is the same. (Since you can't have an editable Grid part and an editable Detail View part in a Grid, there is no need to use different control names for fields in the Grid and Detail View part).
The Name of a field in the Grid Part and Detail View part is:
V.R{Grid.RowNumber}.FIELDNAME
Examples:
V.R3.LASTNAME
V.R-2.FIRSTNAME
Where:
{Grid.componentname} is the alias of the Grid component. The alias is set in the override settings sections in the .a5w page that runs the Grid. Every component that is placed on an .a5w page has to have a unique alias. The alias in the object name is always uppercase.
{Grid.RowNumber} is the row number in the Grid. New record rows have negative row number. E.g. the 2nd new record row has a row number of -2. In the case of a Detail View field, existing rows always have a row number of 1 and new record rows have a row number of -1.
FIELDNAME is the fieldname of the field. In the case of SQL databases, it is possible for fieldnames to include spaces and other special characters. FIELDNAME replaces spaces and special characters with an underscore. E.g. 'LAST NAME' becomes 'LAST_NAME'.
When data is submitted from the server for a new record, the minus sign in the field name is converted to an underscore in the variable name that is created by the Application Server. For example, say that data is submitted from the 2nd new row in a Grid. If you were to examine the list of variables that Firebug reported were submitted to the server, you would see names like these:
V.R-2.LASTNAME
The corresponding variable created by the Application Server (in Request.Variables) is:
V.R_2.LASTNAME
When you define Action Javascript to open a Grid or print a Report, you are prompted for a filter and order expression to apply to the target Grid or Report. If you want the target Grid or Report to inherit the filter and order from the parent Grid, you can use CurrentGridFilter() in in the filter expression. You can actually combine currentGridFilter() with additional filter criteria.
Example
'For a SQL Grid
currentGridFilter() and hasShipped = false
'For a .dbf Grid
currentGridFilter() .and. hasShipped = .f.
The currentGridOrder() expression cannot be combined with any values.
Both the 'Live Preview' and 'Working Preview' let you test how your Grid component works. But unlike the 'Live Preview', the 'Working Preview' does not use the Application Server, or even require that the Application Server be running. The benefit of this is slightly better performance because the overhead of the Application Server is eliminated.
When you go to the 'Live Preview' pane, you are essentially viewing a live web page in Internet Explorer. When you go to the 'Working Preview' pane, Internet Explorer is talking to Alpha Five directly using a special protocol that bypasses the 'http' protocol used when you are running in a browser.
If your Grid contains Javascript events that open Alpha Five reports, or other .a5w pages in pop-up windows, or in DIVs on the Grid, these actions will not work in the Working Preview.
A significant benefit of a Working Preview is that is allows you to easily debug your Xbasic event handlers. Because the Working Preview runs in the foreground thread, you can include debug(1) commands in your Xbasic event handlers to trace into the execution of your scripts.
You can control whether the Working Preview pane is shown in the Grid Builder by selecting the Options, Preferences menu.
When you define a Grid component, you can define Javascript functions and as part of the Grid definition. You can also define custom CSS as part of the Grid. You can also define linked Javascript and CSS files.
For example, you might define the following (trivial) Javascript function in the Grid's 'Javascript function declarations' section:
function sayHello() {
alert('Hello');
}
You might then define a button in the Grid and set the Button's onClick event to:
sayHello();
When you run this Grid and click the button, you get the pop-up message box, as you would expect.
However, if you were to run this Grid in the following scenarios, clicking on the button would not work and you would get a Javascript error:
The reason that the Javascript fails is that it needs to be declared in the .a5w page that loads the 'parent' component. So, for example, in the case of the TabbedUI component, the function 'sayHello' needs to be be defined in the TabbedUI component. But this would mean that you have to duplicate the definition of the sayHello function. You need to define it in the Grid component itself for those situations where the Grid is run by itself. And then you need to define it in the TabbedUI component for those situations where the Grid is run in the TabbedUI component. This is clearly inefficient.
To get around this problem, the TabbedUI, PageLayout and Grid components all have property called 'Linked Resources' that allow you to specify that names of Grid components that contain Javascript and CSS definitions that you want to automatically include when the component is rendered.

This section has miscellaneous topics describing how to perform certain advanced actions with the Grid.
The Grid component does not allow you to base a Grid on a stored procedure. You must specify a SQL Select statement. You can however work around this limitation to a limited degree if your Grid is readonly.
dim tableName as c
tableName = "[PathAlias.ADB_Path]\pir_report.dbf"
pr =a5_RefreshPassiveLinkTable(tableName,.f.,.f.)
Advanced uses might want to use the Tab and Accordion control's onDynamicLoad property to define a Javascript event that will fire when the particular tab/accordion pane gets focus for the first time. This allows you to load dynamic content into the tab/accordion pane only when the pane is visited. If the pane is never visited, then you do not waste time and server resources computing content that will not be seen.
As the image below shows, the third pane (labeled 'DynamicLoad') does not have any controls in it. When the user visits the tab pane, the onDynamicLoad function will fire and it will be set the tab pane content.

This example shows how you can use the onDynamicLoad event for a tab pane to load a Grid component into the tab pane (the Javascript code shown here was copied from an Action Javascript that opened a Grid).
In the example, the target grid is linked on the 'bill_state_region' field using the value from the 'BILL_STATE_REGION' field in the Detail View.
As you can see in the line highlighted in red, the linking value is read (using the _getValue() javascript function) from the Detail View (1st argument of _GetValue())
var go = new Object();
go.gridDiv = 'dv1';
go.gridName = 'Customer';
go.alias = '{Grid.componentname}_Cust_ybvr';
go.submitCurrentFieldValues = true;
go.sourceGridPart = 'D';
go.sourceGridRowNumber = '1';
go.workingMessage = '<img src=\'CSS/A5System/images/wait.gif\'
/>Working...';
go.userFilter = '';
go.baseFilter = '';
go.arguments = '';
go.linkDefinition = 'Bill_state_region(C:[[[data.Bill_state_region]]])';
go.placeHolderValues = 'Bill_state_region =' +{Grid.object}._getValue('D','BILL_STATE_REGION');
go.userOrder = '';
go.overrideSettings = 'Style_name = `{Grid.style}`';
go.a5_default_path = '{grid.defaultPath}';
go.flagTimer = 'F';
go.flagQueryEcho = 'F';
go.flagDebugMode = 'F';
{grid.Object}.openChildGrid(go);
If you want to reset the pane so that it is automatically refreshed when the user visits that pane again, you can execute this javascript:
$('elementId').innerHTML = '';
window['tabObject'].reset();
Where elementId is the Id of the Div in which the pane content is rendered. (Use Firebug in Firefox to examine the HTML to see what the elementId is.
And tabObject is the name of the tab object in which the Pane with the OnDynamicContent function is displayed. Again, use Firebug to examine the code to determine the object name. An example tabObject name is:
GRID1_DVTAB_1R_1Obj
Where 'GRID1' is the Grid Alias, 'R_1' is row 1, and 'DVTAB_1' is the first tab object in the Detail View.
This topic describes how you can write Javascript to open an arbitrary window on the page and put content into the window.
For example, the following Javascript will open a window:
currWindowObject =
A5.PageWindows.createWindow('myWindowId','modeless');
$(currWindowObject.getWindowId('body')).innerHTML = 'this is my window
contents';
currWindowObject.show();
In this example 'currWindowObject' is an arbitrarily named window object, 'myWindowId' is the window name and 'modeless' is the window style. The options for the window style are:
If you call the command multiple times with the same window name, the second and subsequent calls return a pointer to the previously created window.
This means that internally, we are not creating a lot of windows - just one window that gets constantly reused.
It does mean however, that once 'myWindowId' has been created initially, you can't change its type or other property on a subsequent .createWindow() call.
To close the window you execute this Javascript:
currWindowObject.hide();
Where 'currWindowObject' matches the name of the window object in the .createWindow() command above.
The window styles described above can be qualified with the following keywords:
For example:
If you specify the 'url' keyword, then instead of setting the window's innerHTML property, you can set its src property. You would use this option when you want to set the window contents to another .a5w page, or an external page.
For example:
Create a modeless, resizable URL window and display Google.com
win = GRID1_GridObj.createWindow('window2','modeless-resizable-url');
$(win.getWindowId('body')).src = 'http://www.google.com';
Create a modal, resizable URL window and display another .a5w page from the current project
win = GRID1_GridObj.createWindow('window3','modal-resizable-url');
$(win.getWindowId('body')).src = 'page2.a5w?var1=somevarvalue';
If you Grid does a callback that takes some time (e.g. searching a large database), you might want to put up a custom 'working...' message.
This example shows how you can do this for a search, but there are client side events that would enable you to put up custom messages for many different types of actions, including sorting, page navigation, saving data, etc.
Put this in the canSearchSubmit event
A5.msgBox.show('Searching...','<div style=\'padding: 20px;\'>Please wait while we search for the records.</div>','none',function() {});
Put this in the afterSearchSubmit event
A5.msgBox.hide();
If you have defined a client-side calculation involving decimal numbers, and your regional settings define a decimal character other than a period (for example, many countries use a comma as a decimal separator - e.g. 2,5), you will need to make the following adjustments in order to get the calculations to display correctly.
The example below assumes that you have fields called Price, Quantity and Total. You want to define a calculated field for Total using the expression Price * Quantity
1. In the Javascript Declarations Section, add this code:
//Specify the character for the thousands separator
$u.comma = ' ';
//Specify the character for the decimal separator
$u.decimal = ',';
2. Set the 'Display Format' for the Price and Quantity field:
(This is necessary so that the initial display of the data uses a comma as the decimal point. We don't need to set the Display Format for the Total field because the calculation will set the correctly formatted value. )
alltrim(str(<value>,250,2,","))
3. Edit the Calculated field expression and change it to use the str() function which will apply the appropriate number formatting to the result:
alltrim(str(Price * Quantity,250,2,','))
The Dialog Component has not been updated for this release of V10. Since the Grid Component now supports many new features that are not available in the Dialog Component, you might want to use a Grid component instead of a Dialog component in certain cases.
Here is how you can do it:
Create a dummy table with the same fields that you would have had in your Dialog component.
The generic Javascript Watch events make it very easy to dynamically set a control's label at run-time.
For example, say that your Grid has a field called 'COUNTRY'. If the value in COUNTRY is 'USA', you want to set the label on the ZIP field to 'Zip code', otherwise you want to set it to 'Postal Code'.
NOTE: This example assumes that the Grid is set to display data in Form mode.
Here is how you would do it:
var COMPANY = *gv('COMPANY');
var labelValue = 'Zip code';
if( COMPANY != 'USA') labelValue = 'Postal Code';
$('{grid.componentname}.LBL.R' + data.rowNumber + '.'+'ZIP'+'').innerHTML =
labelValue;
In some applications, you might want to set the default value for a field in a new record to be the same as the value in the previously entered field. Here is how you can to this:
This example shows how you can make the lastname field in a new record use the previously entered lastname as a default. Obviously, when you adapt this for your own use, you could define defaults for as many fields as you wanted.
In the AfterInsertRecord event in the Grid builder, define this code:
function AfterInsertRecord as v (e as p)
e.rtc.mydata.lastname = e.datasubmitted.lastname
end function
In the OnIntialValueCalculate event, define this code:
function onInitialValueCalculate as v (e as p)
dim e.rtc.mydata.lastname as c = default ""
if e.rtc.mydata.lastname <> "" then
e.newvalues.lastname = e.rtc.mydata.lastname
end if
end function
In some applications you might we adding or editing data in the table that a Grid is based in another Grid or in some custom Xbasic code. You may want to refresh the Grid that is currently being displayed so that it shows the changes and/or new records that were added in the external process. The Grid object supports three different refresh methods:
For example:
GRID1_GridObj.refreshRow(1)
Where 'GRID1' is the Grid component alias. It must be upper case.
If you have built a Grid that contains Image File Reference fields, and the images are not displaying when you run the Grid, this topic can help you find the problem.
Normally, for an Image File Reference field, the display format in the Field Properties is set to <Image File Reference Field>.
To special display formats are supported to help you debug. These are
In the image shown below, the display format is set to <Image File Reference Filename Raw>
This shows the raw (un-encoded) filename for the image.
As you can see only the first record has an alias name in the image.

In this next example, the display format is set to <Image File Reference Filename>
This shows the decoded filename for each image.
Only the image in the first row was found. That's because the image name used an alias ([FlowerPhotos]) and this alias was defined in the Web Publishing Profile.
Because the image filenames in records 2 and onwards did not use an alias, the filename was decoded at runtime somewhat randomly and the decoded file does not exists.

In order to get this example to work, the image filenames need to be fixed. An xbasic program can be written to loop through all of the records and 'fix' the filenames by using a filename that is encoded with an alias.
t = table.open("flowers")
dim fn as c
while .not. t.fetch_eof()
fn = t.picture
if atc("[FlowerPhotos",fn) = 0 then
fn = word(fn,2,"\"")
fn = "[FlowerPhotos]" + chr(92) + file.filename_parse(fn,"ne")
fn = "=filename_decode(" + quote(fn) +")"
t.change_begin()
t.picture = fn
t.change_end(.t.)
end if
t.fetch_next()
end while
t.close()
Say your Image File Reference Field name is 'image'.
Create two calculated fields as follows:
folder = image
fn = eval(substr(image,2))
Place these calculated fields on your report and make sure that you set the display width of the field to be large enough to display the full size of the field.
The 'calc->folder' calculated field will show the encoded filename of the
image. The 'calc->fn' calculated field will show the actual (un-encoded)
filename.
In V9 you could override any setting of the grid in the Override Settings section in the Xbasic code that loaded the Grid (in the .a5w page).
In V10, this is no longer possible (at least by default). That's because many of the grid template html and other settings are now computed from the Grid properties at design-time, rather than at runtime.
Many properties can still be set at run-time, but some properties cannot (by default). Typically properties that control the layout of the HTML, control definitions, update settings cannot be set at run-time because Alpha Five has already 'processed' these properties.
You can however force A5 to re-calculate certain parts of the Grid (that are normally computed at design-time) at run-time by setting properties of the Grid.
For example, say you want to override a column heading at run-time with this code
tmpl.field_info[3].Column.Heading = "....here is my column heading...."
This will not work because the column headings were computed at run-time,
However, it will work add this property:
tmpl.flagMustRecalculateGridLayoutAndControls = .t.
tmpl.field_info[3].Column.Heading = "....here is my column heading...."
Note: In the above example, if your Grid is set to use a Form view, you can use the slightly faster tmpl.flagMustRecalcGridLayout property. e.g.
tmpl.flagMustRecalcGridLayout = .t.
tmpl.field_info[3].Column.Heading = "....here is my column heading...."
You can set the tmpl.flagMustRecalculateAllProperties property. This forces A5 to re-calculate all aspects of the Grid at run-time. This can be quite slow and should be avoided if possible. (It will delay the initial rendering of the Grid. Once the Grid is rendered, interacting with it will be back to normal speed. There will also be a similar delay when you interact with the Grid if your session expires and a new session needs to be instantiated.)
List of all flags
tmpl.flagMustRecalcGridLayout
tmpl.flagMustRecalcSearchLayout
tmpl.flagMustRecalcDetailViewLayout
tmpl.flagMustRecalculateGridLayoutAndControls
tmpl.flagMustRecalculateDetailViewLayoutAndControls
tmpl.flagMustRecalculateSearchLayoutAndControls
tmpl.flagMustRecalculateAllProperties
The Grid Object has a method that allows you to set the Base Filter for the Grid.
The base filter is normally set in the Grid component. It defines the filter that is always in place. When the user does searches, the search filters are additive to the base filter.
The Grid Object exposes a method to change the base filter.
{Grid.Object}.gridBaseFilterSet(filterExpression [,orderExpression [,parameters]]])
You may want to disable this method to prevent a malicious user from changing the Grid's base filter.
You can do this by setting these Grid properties in the 'Advanced' section on the Grid, Properties pane in the Grid builder:
tmpl.allowBaseFilterSet = .t./.f. 'determines if the base filter can be changed at run-time
tmpl.BaseFilterSetPassword = "mypassword"
If tmpl.BaseFilterSetPassword is not null then the filterExpression in the .gridBaseFilterSet() method must be encrypted (using the a5_encrypt_string() Xbasic function).
When the .gridBaseFilterSet() method is called, the server will use the password to decrypt the filter.
Advanced developers will sometimes insert their own HTML controls in a freeform section for a Grid column. In order to ensure that these user-defined controls get submitted when other controls in the Grid are submitted, you must follow a special naming convention for the controls that you create. The controls must have an ID that matches this pattern:
{Grid.componentname}.YouControlId
For example:
<input id="{grid.componentname}.MYNEWCONTROL" name="MYNEWCONTROL"/>
The control name can be anything you want. If you have a Grid with multiple rows, you will likely want to make the ID unique to each row. For example:
<input id="{grid.componentname}.R{grid.rownumber}.MYNEWCONTROL" name="MYNEWCONTROL"/>
Say you have a Grid component and when the user saves a new record you want to redirect to another page and pass information to that page (such as data values that the user just entered).
Let's assume that the redirect page is called 'Page2.a5w' and you want to pass a variable to this page called EmailAddress which contains the email address just entered by the user.
First, define an 'AfterInsertRecord' event. In this event, add this code:
e.rtc.mydata.emailaddress = e.datasubmitted.emailaddress
The 'rtc' (short for 'run-time calculation') variable is automatically made available to all of the server-side event handlers. Therefore, if you add you own variable to this dot variable, you can pass information from this event handler to another event handler.
Next, define an 'OnPageRedirect' event handler. Add this code:
e.url = "page2.a5w?emailaddress=" + e.rtc.mydata.emailaddress
Note: Since you are handling the redirect by an event, you need to set the
'Target Page' property to '<event>'.
This topic discusses an advanced use of a Custom Control in a Grid component.
The image below shows a grid based on the Invoice_header table from Alphasports. The last column on the Grid shows the line-items (from the Invoice_items table) for the current invoice.
This data in this column is a custom control.

Here is how this was achieved:
1. Create a dummy calculated field. Does not matter what the calculated field is called.
The image below shows how you can do this for .dbf tables.

In the case of SQL tables, you would create a custom SQL Select statement. For example:
SELECT invoice_number, customer_id, date, sales_rep, delivery_by, '' as LinkedItems from Invoice_header
2. Add the calculated field to the Grid and set its control type to the 'Custom'
3. In the 'Custom Control Definition' add this Xbasic:
function Linkeditems_render as c (data as p, args as p,
PageVars as p)
with PageVars
on error goto Linkeditems_xbasicError
linkeditems_render = linkedRecords(Data.Invoice_number,"GlassBlue")
end
Linkeditems_xbasicError:
Linkeditems_render = "Error in custom control xbasic: " + error_text_get()
end with
end function
4. In the 'Xbasic function declarations' section, define the linkedRecords() function.
Here is a version of this function for the case where you are working with DBF files. An example for SQL tables follows below.
function linkedRecords as c (invNo as c, style as c )
dim tbl as p
tbl = table.open("[PathAlias.ADB_Path]\invoice_items")
dim itbl as p
itbl = tbl.query_create("","invoice_number = " + s_quote(invNo))
if itbl.records_get() = 0 then
linkedRecords = "No records found"
exit function
end if
dim htmlTemplate as c
htmlTemplate = <<%html%
<tr>
<td class="{grid.style}DataTD">{a5_html_label(js_escape(tbl.data("product_id")))}</td>
<td class="{grid.style}DataTD" style="text-align:right;">{a5_html_label(js_escape(tbl.data("price")))}</td>
<td class="{grid.style}DataTD" style="text-align:right;">{a5_html_label(js_escape(tbl.data("quantity")))}</td>
<td class="{grid.style}DataTD" style="text-align:right;">{a5_html_label(js_escape(tbl.data("extension")))}</td>
</tr>
%html%
htmlTemplate = stritran(htmlTemplate,"{grid.style}",style)
dim html as c = ""
while .not. tbl.fetch_eof()
*concat(html, evaluate_string(htmlTemplate) + crlf())
tbl.fetch_next()
end while
dim titles as c
titles = <<%html%
<tr>
<th class="{grid.style}SorterLink">Product Id</th>
<th class="{grid.style}SorterLink">Price</th>
<th class="{grid.style}SorterLink">Quantity</th>
<th class="{grid.style}SorterLink">Extension</th>
<th></th>
</tr>
%html%
html = "<table>" + crlf() + titles + crlf() + html + crlf() + "</table>"
html = <<%html%
<fieldset style="-moz-border-radius-topleft: 8px; -moz-border-radius-topright:
8px; -moz-border-radius-bottomright: 8px; -moz-border-radius-bottomleft: 8px;
display: inline;" class="" >
<legend style="color: Blue;" class="">Invoice Items</legend>
%html% + html + "</fieldset>"
tbl.close()
linkedRecords = html
end function
Here is an example for SQL tables:
function linkedRecords as c (invNo as n, style as c )
dim cn as sql::connection
dim flag as l
flag = cn.open("::name::alphasports")
if flag = .f. then
linkedRecords = "Error opening connection"
exit function
end if
dim sql as c
sql = "select * from invoice_items where Invoice_number = :whatInvNo"
dim args as sql::arguments
args.add("whatInvNo",convert_type(invno,"N"))
flag = cn.Execute(sql,args)
if flag = .f. then
linkedRecords = "Error executing query"
exit function
end if
dim rs as sql::resultset
rs = cn.ResultSet
if rs.nextrow() = .f. then
linkedRecords = "No records found."
exit function
end if
dim htmlTemplate as c
htmlTemplate = <<%html%
<tr>
<td class="{grid.style}DataTD">{a5_html_label(js_escape(rs.data("product_id")))}</td>
<td class="{grid.style}DataTD" style="text-align:right;">{a5_html_label(js_escape(rs.data("price")))}</td>
<td class="{grid.style}DataTD" style="text-align:right;">{a5_html_label(js_escape(rs.data("quantity")))}</td>
<td class="{grid.style}DataTD" style="text-align:right;">{a5_html_label(js_escape(rs.data("extension")))}</td>
</tr>
%html%
htmlTemplate = stritran(htmlTemplate,"{grid.style}",style)
dim html as c = ""
dim flagRecordsFound as l = .t.
while flagRecordsFound
*concat(html, evaluate_string(htmlTemplate) + crlf())
flagRecordsFound = rs.nextrow()
end while
dim titles as c
titles = <<%html%
<tr>
<th class="{grid.style}SorterLink">Product Id</th>
<th class="{grid.style}SorterLink">Price</th>
<th class="{grid.style}SorterLink">Quantity</th>
<th class="{grid.style}SorterLink">Extension</th>
<th></th>
</tr>
%html%
html = "<table>" + crlf() + titles + crlf() + html + crlf() + "</table>"
html = <<%html%
<fieldset style="-moz-border-radius-topleft: 8px; -moz-border-radius-topright:
8px; -moz-border-radius-bottomright: 8px; -moz-border-radius-bottomleft: 8px;
display: inline;" class="" >
<legend style="color: Blue;" class="">Invoice Items</legend>
%html% + html + "</fieldset>"
cn.FreeResult()
cn.close()
linkedRecords = html
end function
The Security Framework exposes several functions (listed below for convenience). Some of these functions all implicitly assume that the 'Request', 'Session' and 'Response' server variables will be available. On an a5w page, these variables are available. But in a server-side event handler in a Grid component, you will need to execute a small amount of Xbasic code to make the variables available.
The list below shows which variables each function assumes will be available.
a5ws_add_group() - Request
a5ws_delete_group() - Request
a5ws_delete_user() - Request
a5ws_get_group_assignments() - Request
a5ws_get_groups() - Request
a5ws_get_guid_from_group() - Request
a5ws_get_guid_from_ulink() - Request
a5ws_get_guid_from_user() - Request
a5ws_get_page_list() - Request
a5ws_get_security_ques() - Request
a5ws_get_user_assignments() - Request
a5ws_get_user_from_guid() - Request
a5ws_get_user_values() - Request
a5ws_get_webuser_values() -
a5ws_get_users() - Request
a5ws_lockoutuserrelease() - Request
a5ws_lockoutuserset() Request
a5ws_lockoutuserstatus() - Request
a5ws_login_user() - Request,Session,Response
a5ws_logged_in_user_values() - Request,Session
a5ws_logoutuser() - Session,Request,Response
a5ws_save_webuser_values() - Request
a5ws_securityactive() - Request
a5ws_user_file_field_list() - Request
a5ws_Get_WebUser_Values() - Request
a5ws_Get_WebUser_Values() - Request
a5ws_Save_WebUser_Values() - Request
a5ws_Validate_WebUser_Values() - Request
a5ws_WebUser_Exists() - Request
If the server side event you are using passes in the 'e' object, you will need to add this code to your event handler:
dim request as p
dim session as
dim response as p
request = e.tmpl.request
session = e.rv.session
response = e.tmpl.response
If the server side event you are using passes in 'Args' and 'PageVariables', you will need to add this code to your event handler:
dim request as pp
dim session as
dim response as p
request = args.GridDefinition.request
session = PageVariables.session
response = args.GridDefinition.response
With Action Javascript, it is easy to put a button on a Grid that prints a report. You can easily link the report to data in the current Grid row. For example, if the value of the State field in the current grid row is 'MA', you can easily define a filter for the report that shows all states with a value of 'MA'.
But rather than filter the report based on data in the current row, you might simply want the report to show all of the records that are currently selected in the Grid.
You can easily do this by using the special currentGridFilter() and currentGridOrder() functions in the filter and order expression of your Grid.
The 'Base' filter is the filter that is defined in the Grid component. The user cannot remove this filter by doing a 'Show All'. All searches that the user does are in addition to the base filter. The user filter on the other hand is similar to the filter that the user can apply by performing a search, quick search, alphabet button search, etc. When the user clicks the 'Clear search' hyperlink in the Search Part, the filter set by tmpl.filter_initial is removed.
You can set the base filter and user filter in override settings using these properties:
Examples
'For a SQL database
tmpl.base_filter = "orderdate = {2009-12-31}"
tmpl.base_filter = "quantity > 500"
tmpl.base_filter = "state = 'ma'"
'For a .dbf database
tmpl.base_filter = "orderdate = {12-31-2009}"
tmpl.base_filter = "quantity > 500"
tmpl.base_filter = "state = \"ma\""
Notice that the date/time format for a SQL database is {yyyy-mm-dd} or {yyyy-mm-dd hh:mm:ss}
You can use arguments in the tmpl.base_filter and tmpl.filter_initial properties by specifying a value for the tmpl.argumentValues property.
The syntax for the tmpl.argumentValues property is a CRLF delimited list of argument values defined using this syntax: argumentName|argumentType|argumentValue
Example
'Example 1
tmpl.base_filter = "bill_state_region = :state"
tmpl.argumentValues = "state|c|ca"
'Example 2
tmpl.base_filter = "bill_state_region = :state .and.
order_date = :orderDate"
tmpl.argumentValues = "state|c|ca" + crlf() + "orderDate|d|12/1/07"
You can also specify a Link definition programmatically. A link is similar to a base filter, in that the records are filtered on the link fields, but in addition, when a user enters new records into the Grid, the link fields are automatically set to the linking values. For example, if you link the 'Invoice_Items' Grid on the invoice_number field with a value for invoice_number of '1023', then any new records that are entered into the 'invoice_items' Grid will automatically have their 'invoice_number' field set to '1023'.
To set the link definition, you set the tmpl.linkDefinition property.
The syntax for the linkDefinition is a comma delimited list of link definitions in this format: linkField(type:linkValue)
Examples:
tmpl.linkDefinition = "invoice_number(N:1023)"
tmpl.linkDefinition = "first_name(c:john),lastname(c:smith)"
This topic describes how you can use System Javascript events to show a control on only certain Grid rows. The example we describe here shows a button on row 1 of the Grid only.
To do this, we define an onRowRender System Javascript event that shows the button if we have just rendered row 1 and hides the button is we have rendered any other row.
The following onRowRender event is defined:
var ele = $('{Grid.ComponentName}.V.R' + e.rowNumber + '._UNBOUND_BUTTON_1');
if(e.rowNumber == ) {
ele.style.display = '';
} else {
ele.style.display = 'none';
}
The script gets a pointer to the button on the row that was just rendered, and if the row that was just rendered was row 1, it sets the display style to a null string (which makes the button visible), else, it sets the button's display style to 'none', which hides the button.
The Detail View can be shown in a popup Ajax window. This topic shows how you can define a dynamic title for the window.
In this example, the Detail View is linked to the customer_id field which is displayed in each row of the Grid. We want the Detail View window title to show 'Detail View for Customer - {customer_id}' (where {customer_id} will be dynamically populated).
To do this, define an event handler for the afterDetailViewOpen event and add this code:
row = {grid.object}._detailViewRow
var x = {grid.object}.getValue('G','CUSTOMER_ID',row);
{grid.object}._dvFloatingWindow.setTitle('Detail View for Customer - ' + x);
Using Action Javascript, it is easy to open a Grid or A5W page in a pop-up window. Typically, the window is closed by clicking on the X icon in the window title bar.
However, there may be times where you want a button in the Grid, or an event in the Grid to close the window. The Alpha Five Javascript library provides two functions that allow you to close a pop-up window:
The closeParentA5Window() function takes 'ele' as an argument. 'Ele' is the id of any element in the window. For example, say you would like to have a button to close the current window. Here is how the button would be defined:
<button id="mybutton" onClick="closeParentA5Window(this)">Close this popup
window</button>
The closeLastOpenedA5Window() takes no arguments and closes the most recently
opened pop-up window.
The use of these functions is more complicated if the pop-up window contains an
IFrame and the content in the window is inside the IFrame. This will be the case
if the pop-up window contains an .a5w page.
In this case you will have to do the following:
1. Give the window a unique ID by putting the window title in a <span> tag that assigns an ID. For exmaple
<span id="WINDOWX">My Window Title</span>
2. Use the following Javascript to close the window:
window.parent.closeParentA5Window('WINDOWX');
The 'window.parent' syntax is used to refer to the IFrame's parent window which contains the window you want to close.
The Alphabet Buttons search bar is a useful addition to your Grid if your Grid is displaying a large number of records, but if there are only a few records in the Grid (perhaps because the last search that was run only returned a few records), you might want to hide the Alphabet Buttons search bar.
The following Javascript can be used to dynamically show/hide the Alphabet Buttons Search Bar:
If there are fewer than 5 records in the Grid, the Alphabet Buttons Search Bar will be hidden.
records = {Grid.object}._totalRecordsInGrid;
ele = $('{Grid.ComponentName}.ALPHABETBUTTONS');
minRecords = 5;
if(ele) {
if(records < minRecords ) ele.style.display = 'none';
else ele.style.display = '';
}
This code should be added to the 'afterAjaxCallbackComplete' event in the Javascript - System Events category.
The Grid object exposes many methods that you can call from Javascript event handlers in your Grid components. Typically, your Javascript looks like this:
{grid.object}.methodName();
'{grid.object}' is a placeholder that gets replaced with the Grid object alias at run-time.
There are situations where a Grid is opened as a child of a parent Grid and you want to execute a method on the the Grid's parent Grid. In this case, you can't use the {Grid.object} placeholder. You will need to get a pointer to the Grid's parent Grid object in your Javascript code.
For example, say that you want to put a button on a Grid that will cause its parent Grid to refresh. Here is how you can do this:
//Get a pointer to the parent Grid
var po = {Grid.object}.getParentObject();
//If this Grid is not a child Grid, then po will be false. Only call the .refresh() method if po is not false.
if(po) po.refresh();
Note: You can get the name of the parent Grid's alias from the Grid object's .parentGridAlias property. For example, try putting this Javascript on a button in a Grid.
var myParent = {grid.object}.parentGridAlias;
var me = {grid.object}.gridID;
var message = 'My alias: ' + me + '\nMy parent alias: ' + myParent;
alert(message);
JQuery is a popular open-source Javascript Library that can be used to add client-side functionality to your web applications. In order to use JQuery with Alpha Five it is necessary to configure JQuery to not use the $ character as the JQuery object name. This is because the $ character is used in the Alpha Five Javascript function libraries. The Alpha Five Javascript function $() is used as a shorthand for the Javascript .getElementById() method.
The following Javascript can be added to the page just after the JQuery library is loaded:
<script type="text/javascript">
var $j = jQuery.noConflict();
</script>