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.
Note: Your code must ensure the srvroutine uses the correct number of keys by passing them with a value or a null value.

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

 Note: SearchName is an edit box. It has a default property Value, meaning it can be used like a field, as a search value passed to the srvroutine.

     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 

Note: For consistent design, you would usually define this routine as a method. This exercise uses a subroutine simply as a coding example.

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      

Note: The sequence of the variables passed to the execute srvroutine is significant. The given name search receives a given name followed by surname.

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.

 Note: Remember the name fields contain proper case text. Your first character should be upper case. You could implement a search which is non-case sensitive using the SELECT_SQL command. You could also add code to ensure the first character is upper case, for example, this line could be added, before executing SurnameSearch.

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

  • No labels