Validates data in the UX Component that was submitted.
When validating information that a user inputs, you may want to return an error message when some combination of fields does not meet a certain validation rule. In these instances it is easier to define the validation rule at the component level. Rather than adding validation rules to multiple fields in the 'Field Properties' section of the UX Controls page you can define on validation rule that will run on the server when the dialogValidate event fires.
Data values that were submitted are in e.dataSubmitted (original values are in e.oldDataSubmitted) The list of dirty submitted fields is in: e.dirtyColumns. This is a CRLF delimited string of dirty fields (i.e. fields edited by the user). For example:
If your event handler modifies a value in the e.dataSubmitted object (and that field has NOT been edited by the user), you MUST explicitly add the field to the e.dirtyColumns value yourself. For example, assume that you want to set the Company field to 'Alpha' and the 'Qty' field in row 1 of a repeating section regardless of whether the user edited the value or not:
e.dataSubmitted.COMPANY = "alpha" e.dataSubmitted.QTY_A5INSTANCE2 = "2" e.dirtyColumns = e.dirtyColumns + crlf()+ "COMPANY" + crlf() + "QTY_A5INSTANCE2"
If your dialog contains repeating sections, data in the repeating sections will be in an array. For example, say that your dialog has a repeating section that includes a field called QTY:
Contains data from first repeating section row
Contains data from second repeating section row, etc
Contains data from the second row - 'favoriteColors' is a multi-select control - returns the 3rd choice the user made
Number of entries in the array.
In addition, the e object will contain information about the repeating sections
A comma delimited list of the name (container ID) or each repeating section
A property array with one entry for each repeating section.
The e.repeatingSectionInfo array will have these properties for each entry:
The row in the repeating section that had focus when the Dialog was submitted
A CRLF delimited list of rows that were deleted. e.g. 1 and 3
A count of the number of non-deleted rows
A count of all rows in the repeating section including rows that were deleted
- .fieldsInRepeating section
A CRLF delimited list of fields in the repeating section
A CRLF delimited list of rows in the repeating section that were edited. (A row that was edited, then deleted will still appear in this list).
A CRLF delimited list of fields in the repeating section that were edited. for example: PARTNO_A5INSTANCE3 is the 'PARTNO' field in row 3.
The Request object. Includes Request.Variables, which should be used instead of the older e.rv construct
The Session object. Should be used instead of the older e.session construct
Runtime calculations - you can use this to store data to be passed to other server side events (Note: the 'rtc' object cannot be used to persist state information - i.e. you can't set a value in rtc and then read that value in a subsequent callback. To persist state info see e._state).
SQL::Arguments object with values for each of the arguments defined in this component. To read a value from arguments: e.arguments.find("argumentName").data
This event can set the value of any of the control in the Browser after it executes. For example:
e.control.firstname = "Fred" e.control.lastname = "Jones"
e._set.firstname.value = "Fred" e._set.firstname.style.color = "red" e._set.firstname.style.fontSize = "20" e._set.firstname_a5instance3.value = "Fred" 'sets value in 3rd Repeating Section row
If you set the property of a field in a repeating section without explicitly stating what row in the repeating section you are addressing, the field in the row with focus is set. For example, assume that the QTY field is in a repeating section. The following sets the value of the QTY field in the repeating section row that has focus
e._set.qty.value = "23"
To set the value of the QTY field in the 3rd repeating instance row do this:
e._set.qty_A5INSTANCE3.value = "23"
Your code must set these properties
dialogValidate.hasError = .f. dialogValidate.errorText = ""
By setting the above properties, you cause a global error message to show on the Dialog. If you want error messages to appear next to particular fields, you can set properties in this optional array. For example:
dim dialogValidate.fieldErrors as p i = dialogValidate.fieldErrors.append() dialogValidate.fieldErrors[i].varname = "FIRSTNAME" dialogValidate.fieldErrors[i].errorText = "Error message for the FIRSTNAME field" i = dialogValidate.fieldErrors.append() dialogValidate.fieldErrors.varname = "QUANTITY:3" dialogValidate.fieldErrors[i].errorText = "Error message for the QUANTITY field in the 3rd row of a Repeating Section"
If you have set field level error using the dialogValidate.fieldErrors array, you might want to suppress the global error message from appearing. To do this, set
dialogValidate.errorText = "No Message"
Example validation code: (Notice that all data values in e.dataSubmitted and e.oldDataSubmitted are Character values. You must use convert_type() to convert it to the correct data type)
if e.dataSubmitted.lastname = "Smith" .and. convert_type(e.datasubmitted.accountType,"N") > 2 then dialogValidate.hasError = .t. dialogValidate.errorText = "Invalid order" end if
Example for a field in a repeating section
dim i as n dim count as n count = e.dataSubmitted.qty.size() 'Loop over each entry in the array of data that was submitted for i = 1 to count if convert_type(e.dataSubmitted.qty[i],"N") > 10 then dialogValidate.hasError = .t. dialogValidate.errorText = dialogValidate.errorText + "Quantity in row " + i + "must be less than 10 <br>" end if next i
You can set 'state' variables in this event. The value of any state variables will be available in all subsequent ajax callbacks. To set a state variable:
e._state.myvar1 = "value1" e._state.myvar2 = "value2"
To read the value of a 'state' variable that was previously set:
In the UX Builder on the UX Controls page open the 'Data Controls' menu. Click on the [TextBox] option to add a textbox control to the component. Give the textbox control the name and label 'first_name'.
Add a second [TextBox] control to the component. Give this control the name and label of 'last_name'.
Click on the [TextBox] option a third time to add a third textbox control to the component. Give this control the name and label 'company'
Open the 'Defined Controls' menu and click on the 'Submit-Reset' option to add submit and reset buttons to the component.
From the 'Events' dropdown on the main menu open the 'Server-Side Events' page. Highlight the 'dialogValidate' event in the Server-Side Events menu.
Define the dialogValidate function using the following Xbasic.
function dialogValidate as p (e as p) dialogValidate.hasError = .f. dialogValidate.errorText = "" dim ds as p ds = e.dataSubmitted if ds.company = "alpha" then if .not. (ds.first_name = "John" .and. ds.last_name = "Jones" ) then dialogValidate.hasError = .t. dialogValidate.errorText = "The only valid name if company is 'Alpha' is John Jones" end if end if end functionTo make things easier to write 'e.dataSubmitted' is assigned first to the variable ds. This new variable is used to create two if statments. In the first statement, if the company field is 'Alpha' then the second if statement will be executed. This second statement returns an error message when the first and last name fields are not equal 'John' and to 'Jones'.
Run the component in Live Preview. Enter a name and then enter 'alpha' into the 'Company' field. If the name you entered is not John Jones then you should receive the error message that you defined in Server-side events. If the company field does is not 'alpha' the error message will not be shown.