In this step, you will add logic to the web page to load departments, employees and employee notes to the list.
For this web page, you want to load all departments, employees and employee note data from the server initially. You will do this by invoking a LoadData method from the web page CreateInstance event routine, which runs before the page data is displayed. The LoadData method will invoke routines which get department, employee and employee note data from the server, before then populating the list.
1. Copy and paste these working list definitions into your web page:
a. Copy xDepartmentsList from the server module iiixDepartmentsDataServer.
b. Copy xEmployeeList from server module iiixEmployeeDataServer
c. Copy xEmployeeNotesList from server module iiixEmployeeNotesDataServer
2. Create a LoadData method routine. This will retrieve a list of departments and then invoke a GetEmployees method routine. The routine should perform the following:
Define a component for iiixDepartmentsDataServer, FindAll srvroutine, named GetDepts
Execute GetDepts asynchronously, exchanginging list xDepartmentsList
Within an event routine for GetDepartments.Completed
Invoke GetEmployees
End routine
Your code should look like the following:
Mthroutine Name(LoadData)
Define_Com Class(#iiixDepartmentsDataServer.findall) Name(#GetDepts)
#GetDepts.executeasync( #xDepartmentsList )
Evtroutine Handling(#GetDepts.Completed)
#COM_SELF.GetEmployees
Endroutine
Endroutine
3. Create a GetEmployees method routine which performs the following:
Define a component for iiixEmployeeDataServer, FindAll, named GetEmployees
Execute GetEmployees asynchronously, exchanging #xEmployeeList
Within an event routine for GetEmployees.Completed
Invoke GetNotes
End routine
Your code should look like the following:
Mthroutine Name(GetEmployees)
Define_Com Class(#iiixEmployeeDataServer.findall) Name(#GetEmployees)
#GetEmployees.ExecuteAsync( #xEmployeeList )
Evtroutine Handling(#GetEmployees.Completed)
#COM_SELF.GetNotes
Endroutine
Endroutine
4. Create a GetNotes method routine, to perform the following:
Define a component for iiixEmployeeNotesDataServer, FindAll srvroutine, named GetNotes
Execute GetNotes asynchronously, exchanging list xEmployeeNotesList
Within an event routine for GetNotes.Completed
Invoke LoadDepts
End Routine
Your code should look like the following:
Mthroutine Name(GetNotes)
Define_Com Class(#iiixEmployeeNotesDataServer.findall) Name(#GetNotes)
#GetNotes.EXECUTEASYNC( #xEmployeeNotesList )
Evtroutine Handling(#GetNotes.Completed)
#COM_SELF.LoadDepts
Endroutine
Endroutine
The LoadDepts routine is not yet created.
5. In this step you will create an AddEntry method which will add entries to the list for each of the three levels. The method AddEntry will be invoked by routines which load all departments, load employees for each department and load notes for each employee to the list.
As well as the data to populate the three columns, the routine will be passed a reference to an image component for each level and a reference to the parent list item for each level. For example, a department is parent to employee entries for that department.
Create a method routine, with the name AddEntry and private access.
Define three maps for input of class STD_OBJ, STD_DESC and DESCL with names Column1, Column2 and Column3.
Make Column2 and Column3 optional by giving them a Mandatory(" ") keyword. Maps with a mandatory keyword, are optional parameters for the method.
Define a map for input of class prim_bmp (a basic graphic) with name Image, with a null mandatory value and to be passed by reference.
Define a map for input of class prim_list.ListItem (a primitive list item) with the name ParentItem, a null mandatory value to be passed by reference.
Define a map for result, class prim_list.ListItem, name Result and a null mandatory value.
Your code should look like the following:
Mthroutine Name(AddEntry) Access(*private)
Define_Map For(*Input) Class(#std_obj) Name(#Column1)
Define_Map For(*Input) Class(#std_desc) Name(#Column2) Mandatory("")
Define_Map For(*Input) Class(#std_descl) Name(#Column3) Mandatory("")
Define_Map For(*Input) Class(#prim_bmp) Name(#Image) Mandatory(*null) Pass(*by_reference)
Define_Map For(*Input) Class(#Prim_list.ListItem) Name(#ParentItem) Mandatory(*null) Pass(*by_reference)
Define_Map For(*Result) Class(#Prim_list.ListItem) Name(#Result) Mandatory(*null) Pass(*by_reference)
Endroutine
6. Extend the AddEntry method routine to perform the following:
Assign the input parameters Column1, Column2 and Column3 values to the list columns, std_obj, std_desc and std_descl respectively.
Add an entry to the list component, named List.
Set a reference to the List current item, ParentItem property to the reference passed as ParentItem.
Set a reference to the List current item, Image property to the reference passed as Image.
Set a reference to Result from List.CurrentItem
Your code should now look like the following. New code is shown highlighted.
Mthroutine Name(AddEntry) Access(*private)
Define_Map For(*Input) Class(#std_obj) Name(#Column1)
Define_Map For(*Input) Class(#std_desc) Name(#Column2) Mandatory("")
Define_Map For(*Input) Class(#std_descl) Name(#Column3) Mandatory("")
Define_Map For(*Input) Class(#prim_bmp) Name(#Image) Mandatory(*null) Pass(*by_reference)
Define_Map For(*Input) Class(#Prim_list.ListItem) Name(#ParentItem) Mandatory(*null) Pass(*by_reference)
Define_Map For(*Result) Class(#Prim_list.ListItem) Name(#Result) Mandatory(*null) Pass(*by_reference)
#std_obj := #Column1
#std_desc := #Column2
#std_descl := #Column3
Add_Entry To_List(#List)
#List.Currentitem.ParentItem <= #ParentItem
#List.Currentitem.image <= #Image
#Result <= #List.Currentitem
Endroutine
7. Create a method routine with the name LoadDepts, to perform the following:
Read the working list Departments in a Selectlist/Endselect loop.
For each entry:
Invoke AddEntry passing values xDepartmentCode, xDepartmentDescription, "" and xImageDepartment32
Invoke LoadEmployees passing values xDepartmentCode and List.CurrentItem
End Read
Note: xImageDepartment32 is an image component in the Repository.
Your code should look like the following. The LoadEmployees method is not yet written.
Mthroutine Name(LoadDepts)
Selectlist Named(#xDepartmentsList)
#COM_SELF.AddEntry( #xDepartmentCode #xDepartmentDescription "" #xImageDepartment32 )
#COM_SELF.LoadEmployees( #xDepartmentCode #List.CurrentItem )
Endselect
Endroutine
8. Create a LoadEmployees method routine to perform the following:
Define a map for input of class xDepartmentCode with the name DeptCode
Define a map for input of class Prim_List.ListItem with the name Parent, passed by reference
Read the working list xEmployeeList in a selectlist/endselect loop, where DeptCode is equal to xDepartmentCode
For each entry:
Invoke Addentry passing values xEmployeeIdentification, xEmployeeSurname, xEmployeeGivenNames, xImageEmployee32 and Parent
Invoke LoadNotes passing values xEmployeeIdentification and List.CurrentItem
LoadNotes is not yet written.
Your code should look like the following:
Mthroutine Name(LoadEmployees)
Define_Map For(*INPUT) Class(#xDepartmentCode) Name(#DeptCode)
Define_Map For(*INPUT) Class(#prim_list.listitem) Name(#parent) Pass(*BY_REFERENCE)
Selectlist Named(#xEmployeeList) Where(#DeptCode = #xDepartmentCode)
#COM_SELF.AddEntry( #xEmployeeIdentification #xEmployeeSurname #xEmployeeGivenNames #xImageEmployee32 #parent )
#COM_SELF.LoadNotes( #xEmployeeIdentification #List.CurrentItem )
Endselect
Endroutine
9. Create a LoadNotes method routine to perform the following:
Define a map for input of class xEmployeeIdentification with the name EmployID
Define a map for input of class Prim_List.ListItem with the name Parent, passed by reference
Read the working list xEmployeeNotesList in a Selectlist/endselect loop where EmployID is equal to xEmployeeIdentification
For each entry:
Invoke Addentry passing values xEmployeeNoteCreateUpdate as display string, xEmployeeNote, "", xImageDetails32 and Parent
Your code should look like the following:
Mthroutine Name(LoadNotes)
Define_Map For(*INPUT) Class(#xEmployeeIdentification) Name(#EmployID)
Define_Map For(*INPUT) Class(#prim_list.listitem) Name(#parent) Pass(*BY_REFERENCE)
Selectlist Named(#xEmployeeNotesList) Where(#EmployID = #xEmployeeIdentification)
#COM_SELF.AddEntry( #xEmployeeNoteCreateUpdate.AsDisplayString #xEmployeeNote.AsNativeString.trim "" #xImageDetails32 #parent )
Endselect
Endroutine
10. Create a CreateInstance event routine for the web page. Add code to invoke LoadData.
Evtroutine Handling(#com_owner.createInstance)
#com_self.Loaddata
Endroutine
11. Compile your web page.
12. Test your web page. Since the web page is loading all departments, employees and employee notes initially, you will notice a few seconds delay while this happens. Each entry in the list is automatically given a small arrow icon indicating it has children and may be expanded. When you expand an entry, there will be no delay since all tree entries were added to the list control initially.