dialogValidate

Description

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:

FIRSTNAME
QTY_A5INSTANCE3

Important 

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"

Repeating Sections 

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:

e.dataSubmitted.qty[1]

Contains data from first repeating section row

e.dataSubmitted.qty[2]

Contains data from second repeating section row, etc

e.dataSubmitted.favoriteColors[2][3]

Contains data from the second row - 'favoriteColors' is a multi-select control - returns the 3rd choice the user made

e.dataSubmitted.qty.size()

Number of entries in the array.

In addition, the e object will contain information about the repeating sections

e.repeatingSectionNames

A comma delimited list of the name (container ID) or each repeating section

e.repeatingSectionInfo

A property array with one entry for each repeating section.

The e.repeatingSectionInfo[] array will have these properties for each entry:

.activeRow

The row in the repeating section that had focus when the Dialog was submitted

.deletedRows

A CRLF delimited list of rows that were deleted. e.g. 1 and 3

.rowCount

A count of the number of non-deleted rows

.totalRowCount

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

.dirtyRowsInSection

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).

.dirtyFieldsInSection

A CRLF delimited list of fields in the repeating section that were edited. for example: PARTNO_A5INSTANCE3 is the 'PARTNO' field in row 3.

Request 

The Request object. Includes Request.Variables, which should be used instead of the older e.rv construct

Session 

The Session object. Should be used instead of the older e.session construct

Also inside e: 

e.tmpl

Component definition

e.rtc

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).

e.arguments

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"
You can also use the 'e._set' syntax here:
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

Setting Properties of Fields in Repeating Sections 

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[0] 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"

Optional. Set the 'e.javascript'' property if you want to send some javascript back to the browser:

e.javascript

Examples 

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:

e._state.myvar1

Using the dialogValidate Event 

  1. 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'.

  2. Add a second [TextBox] control to the component. Give this control the name and label of 'last_name'.

  3. 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'

  4. Open the 'Defined Controls' menu and click on the 'Submit-Reset' option to add submit and reset buttons to the component.

  5. From the 'Events' dropdown on the main menu open the 'Server-Side Events' page. Highlight the 'dialogValidate' event in the Server-Side Events menu.

  6. 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 function
    To 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'.
  7. 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.

See Also