In this step, you will add two method routines to the web page which will execute a srvroutine to perform a search using the index xEmployeeByGiveName or xEmployeeBySurname, adding entries from the returned list of employees to the List control,
EmployeeList on the web page.
You will notice that all searches will be handled using a common coding structure:
The SEARCH button click event routine invokes a Search method. The Search routine:
Defines a component for the Server Module / Srvroutine to be called. The srvroutine is given an appropriate name, for example SurnameSearch
SurnameSearch is executed asynchronously (executeasync) passing parameters to be sent and received.
When the SurnameSearch.Completed event is signaled
The EmployeeList control is cleared
The returned working list is processed using Selectlist/endselect loop
For each entry, execute a subroutine to set up columns and add entry to EmployeeList list control.
Your design needs to consider the following points:
- Invoking the srvroutine asynchronously means that changes may occur in web page variables while the Server Module processing is handled.
- In particular your web page variables may be changed due to mouse over or focus events on a list component.
- You may choose to define the list columns sourced using fields which do not appear in the table definition or alternatively handle selected object details in a separate (reusable part) component.
- It is usually a good design strategy to pass a key value into the data retrieval method, so that its value cannot be changed by the list events mentioned above.
- The Server Module which may be generated for a table, includes srvroutines Delete, Find, FindAll, FindPage, and Save.
- The generated server module also has a srvroutine for each index over the physical table. This routine reads the table with all the index's keys, including parameters Nbr_key(*compute) and Generic(*yes).
- With three table keys for example, the Nbr_Keys(*compute) parameter means the srvroutine can return a list of records based on one, two or three keys as appropriate. If the third key has a null value for example, the table is read using the two higher level keys only, and so on.
1. Create a SurnameSearch method routine, based on the following:
Define a component for server module iiixEmployeeDataServer / FindxEmployeeBySurna srvroutine with name SurnameSearch
Assign a null value to Given Names
Execute SurnameSearch asynchronously passing fields SearchName and Given Names and the list xEmployeeList.
Within an event routine for SurnameSearch.Completed
Execute a subroutine LoadEmpList (not yet defined)
End routine
Your code should look like the following:
Mthroutine Name(SurnameSearch) Define_Com Class(#iiixEmployeeDataServer.FindxEmployeeBySurna) Name(#SurnameSearch) #xEmployeeGivenNames := *null #SurnameSearch.ExecuteAsync( #SearchName #xEmployeeGivenNames #xEmployeeList ) Evtroutine Handling(#SurnameSearch.completed) Execute Subroutine(LoadEmplist) Endroutine Endroutine
Subroutine LoadEmpList is defined in the next step.
2. This step defines a common subroutine to be executed by each search method routine.
Define a subroutine, named LoadEmpList, based on the following:
Clear the list component, EmployeeList
Select all entries in the working list, xEmployeeList.
For each entry:
Assign a value to each EmployeeList column:
std_obj = xEmployeeIdentification
Fullname = xEmployeeSurname + ', ' + xEmployeeGivenNames
std_codel = xDepartmentCode
std_desc = xDepartmentDescription, retrieved from xDepartmentList
Std_datex = xEmployeeStartDate.
Add each entry to list EmployeeList
End Select
Assign Group_by xEmployee fields to null
Your code should look like the following:
Subroutine Name(LoadEmpList) Clr_List Named(#EmployeeList) Selectlist Named(#xEmployeeList) #std_obj := #xEmployeeIdentification #std_codel := #xDepartmentCode Loc_Entry In_List(#xDepartmentsList) Where('#std_codel = #xDepartmentCode') #std_desc := #xDepartmentDescription #iiiFullName := #xEmployeeSurname + ', ' + #xEmployeeGivenNames #std_datex := #xEmployeeStartDate Add_Entry To_List(#EmployeeList) Endselect #xEmployee := *null Endroutine
3. Copy the SurnameSearch method to create a GivenNameSearch method routine.
Modify the code based on the following:
Use the FindxEmployeeByGiven srvroutine with name GivenNameSearch
Assign Surname to *null
Execute GivenNameSearch passing SearchName, Surname and list xEmployeeList.
Change evtroutine to handle GivenNameSearch.Completed.
Your code should look like the following:
Mthroutine Name(GivenNameSearch) Define_Com Class(#iiixEmployeeDataServer.FindxEmployeeByGiven) Name(#GivenNameSearch) #xEmployeeSurname := *null #GivenNameSearch.ExecuteAsync( #SearchName #xEmployeeSurname #xEmployeeList ) Evtroutine Handling(#GivenNameSearch.completed) Execute Subroutine(LoadEmplist) Endroutine Endroutine
4. Complete the Button_Search.Click event routine, based on the following:
Define a CASE loop for the field STD_NAME (search type):
When = 'Surname', invoke SurnameSearch.
When = 'Given Name', invoke GivenNameSearch.
Your code should look like the following:
Evtroutine Handling(#Button_Search.Click) Case Of_Field(#std_name) When (= 'Surname') #com_self.SurnameSearch When (= 'Given Name') #com_self.GivenNameSearch Endcase Endroutine
5. Compile and test your web page. Search for employees and select one. You should now be able to perform a search by surname or given name.
. . . #SearchName := #SearchName.value.replacesubstring( 1 1 #SearchName.value.uppercase.substring( 1 1 ) ) #SurnameSearch.ExecuteAsync( #SearchName #xEmployeeGivenNames #xEmployeeList ) . . .
If your search does not return employees when expected, remember to investigate using debug.