Example 2: Show Employee Details and Skills

This example is an extension of the previous one. It shows the same details but it also shows the skills in a Visual LANSA list view.

 

In this example you can see how to access a subfile/browselist:

 

Function Options(*DIRECT)

 

Begin_Com Role(*EXTENDS #VF_AC010) Height(569) Layoutmanager(#MAIN_LAYOUT) Width(776)

 

* ================================================================================

* Simple Field and Group Definitions

* ================================================================================

 

Group_By Name(#XG_HEAD) Fields(#EMPNO #SURNAME #GIVENAME #ADDRESS1 #ADDRESS2 #ADDRESS3 #POSTCODE #PHONEHME #DEPTMENT #SECTION)

 

* Body and Button arrangement panels

Define_Com Class(#PRIM_PANL) Name(#BUTTON_PANEL) Displayposition(2) Height(569) Hint(*MTXTDF_DET1) Layoutmanager(#BUTTON_FLOW) Left(688) Parent(#COM_OWNER) Tabposition(3) Tabstop(False) Top(0) Width(88)

 

Define_Com Class(#PRIM_PANL) Name(#BODY_HEAD) Displayposition(1) Height(569) Hint(*MTXTDF_DET1) Layoutmanager(#BODY_HEAD_FLOW) Left(0) Parent(#COM_OWNER) Tabposition(2) Tabstop(False) Top(0) Verticalscroll(True) Width(688)

 

* Attachment and flow layout managers

Define_Com Class(#PRIM_ATLM) Name(#MAIN_LAYOUT)

Define_Com Class(#PRIM_FWLM) Name(#BUTTON_FLOW) Direction(TopToBottom) Flowoperation(Center) Marginbottom(4) Marginleft(4) Marginright(4) Margintop(4) Spacing(4) Spacingitems(4)

 

Define_Com Class(#PRIM_FWLM) Name(#BODY_HEAD_FLOW) Direction(TopToBottom) Marginbottom(4) Marginleft(4) Marginright(4) Margintop(4) Spacing(4) Spacingitems(4)

 

Define_Com Class(#PRIM_FWLI) Name(#FWLI_EMPNO) Manage(#EMPNO) Parent(#BODY_HEAD_FLOW)

Define_Com Class(#PRIM_FWLI) Name(#FWLI_SURNAME) Manage(#SURNAME) Parent(#BODY_HEAD_FLOW)

Define_Com Class(#PRIM_FWLI) Name(#FWLI_GIVENAME) Manage(#GIVENAME) Parent(#BODY_HEAD_FLOW)

Define_Com Class(#PRIM_FWLI) Name(#FWLI_ADDRESS1) Manage(#ADDRESS1) Parent(#BODY_HEAD_FLOW)

Define_Com Class(#PRIM_FWLI) Name(#FWLI_ADDRESS2) Manage(#ADDRESS2) Parent(#BODY_HEAD_FLOW)

Define_Com Class(#PRIM_FWLI) Name(#FWLI_ADDRESS3) Manage(#ADDRESS3) Parent(#BODY_HEAD_FLOW)

Define_Com Class(#PRIM_FWLI) Name(#FWLI_POSTCODE) Manage(#POSTCODE) Parent(#BODY_HEAD_FLOW)

Define_Com Class(#PRIM_FWLI) Name(#FWLI_PHONEHME) Manage(#PHONEHME) Parent(#BODY_HEAD_FLOW)

Define_Com Class(#PRIM_FWLI) Name(#FWLI_SAVE_BUTTON) Manage(#SAVE_BUTTON) Parent(#BUTTON_FLOW)

 

* The save button

 

Define_Com Class(#PRIM_PHBN) Name(#SAVE_BUTTON) Caption(*MTXTDF_SAVE) Displayposition(1) Left(4) Parent(#BUTTON_PANEL) Tabposition(1) Top(4)

 

* Collection for detail fields

 

Define_Com Class(#Prim_ACol<#prim_evef>) Name(#PanelFields)

 

* Fields in the head area

 

Define_Com Class(#EMPNO.Visual) Displayposition(1) Height(19) Hint(*MTXTDF_DET1) Left(4) Parent(#BODY_HEAD) Tabposition(1) Top(4) Usepicklist(False) Width(209)

Define_Com Class(#SURNAME.Visual) Displayposition(2) Height(19) Hint(*MTXTDF_DET1) Left(4) Parent(#BODY_HEAD) Tabposition(2) Top(27) Usepicklist(False) Width(324)

Define_Com Class(#GIVENAME.Visual) Displayposition(3) Height(19) Hint(*MTXTDF_DET1) Left(4) Parent(#BODY_HEAD) Tabposition(3) Top(50) Usepicklist(False) Width(324)

Define_Com Class(#ADDRESS1.Visual) Displayposition(4) Height(19) Hint(*MTXTDF_DET1) Left(4) Parent(#BODY_HEAD) Tabposition(4) Top(73) Usepicklist(False) Width(363)

Define_Com Class(#ADDRESS2.Visual) Displayposition(5) Height(19) Hint(*MTXTDF_DET1) Left(4) Parent(#BODY_HEAD) Tabposition(5) Top(96) Usepicklist(False) Width(363)

Define_Com Class(#ADDRESS3.Visual) Displayposition(6) Height(19) Hint(*MTXTDF_DET1) Left(4) Parent(#BODY_HEAD) Tabposition(6) Top(119) Usepicklist(False) Width(363)

Define_Com Class(#POSTCODE.Visual) Displayposition(7) Height(19) Hint(*MTXTDF_DET1) Left(4) Parent(#BODY_HEAD) Tabposition(7) Top(142) Usepicklist(False) Width(216)

Define_Com Class(#PHONEHME.Visual) Displayposition(8) Height(19) Hint(*MTXTDF_DET1) Left(4) Parent(#BODY_HEAD) Tabposition(8) Top(165) Usepicklist(False) Width(286)

 

Define_Com Class(#PRIM_ATLM) Name(#ATLM_1)

Define_Com Class(#PRIM_ATLI) Name(#ATLI_1) Attachment(Center) Parent(#ATLM_1)

Define_Com Class(#PRIM_ATLI) Name(#ATLI_2) Attachment(Center) Manage(#BODY_HEAD) Parent(#MAIN_LAYOUT)

Define_Com Class(#PRIM_ATLI) Name(#ATLI_3) Attachment(Right) Manage(#BUTTON_PANEL) Parent(#MAIN_LAYOUT)

 

Define_Com Class(#PRIM_ATLI) Name(#ATLI_4) Attachment(Center) Parent(#MAIN_LAYOUT)

Define_Com Class(#PRIM_ATLI) Name(#ATLI_6) Attachment(Center) Parent(#MAIN_LAYOUT)

 

Define_Com Class(#PRIM_FWLI) Name(#FWLI_1) Parent(#BODY_HEAD_FLOW)

 

Define_Com Class(#PRIM_LTVW) Name(#skills) Componentversion(2) Displayposition(9) Fullrowselect(True) Height(229) Left(4) Parent(#BODY_HEAD) Showsortarrow(True) Tabposition(9) Top(188) Width(485)

Define_Com Class(#PRIM_LVCL) Name(#LVCL_1) Caption('Acquired') Captiontype(Caption) Displayposition(1) Parent(#skills) Source(#VF_ELTXTS) Width(18) Widthtype(Fixed)

Define_Com Class(#PRIM_LVCL) Name(#LVCL_2) Displayposition(2) Parent(#skills) Source(#SKILCODE) Width(17)

Define_Com Class(#PRIM_LVCL) Name(#LVCL_3) Captiontype(ColumnHeadings) Displayposition(3) Parent(#skills) Source(#SKILDESC) Width(32)

Define_Com Class(#PRIM_LVCL) Name(#LVCL_4) Captiontype(ColumnHeadings) Displayposition(4) Parent(#skills) Source(#COMMENT) Width(24)

Define_Com Class(#PRIM_LVCL) Name(#LVCL_5) Displayposition(5) Parent(#skills) Source(#GRADE) Width(8) Widthtype(Characters)

 

Define_Com Class(#vf_sy122) Name(#myscreen_wrapper) Displayposition(3) Height(569) Parent(#COM_OWNER) Width(688)

 

* =================================================================================================

* To better understand this example you should be famililar with the shipped Personnel System demo.

*

* We expect the following screens to appear as part of this navigation:

*

* Login -> type in user and password -> press Enter -> (a special screen? <F3>)

* i5 Main Menu -> type lansa run process(pslsys) partition(dem) -> press Enter

* Personnel System  -> type option 3 -> press Enter

* Inquire -> type the current instance employee number -> press Enter

* Browse Employee Details and Skills in OUTPUT mode -> press F21

* Browse Employee Details and Skills in INPUT mode

* =================================================================================================

*

* Handle Initialization

* --------------------------------------------------------------------------------

 

Mthroutine Name(uInitialize) Options(*REDEFINE)

 

Define_Com Class(#Prim_evef) Name(#FormField) Reference(*dynamic)

 

Invoke Method(#Com_Ancestor.uInitialize)

 

For Each(#Control) In(#Body_Head.ComponentControls)

 

If_Ref Com(#Control) Is(*INSTANCE_OF #prim_evef)

 

Set_Ref Com(#FormField) To(*dynamic #Control)

 

Invoke Method(#PanelFields.Insert) Item(#FormField)

 

Endif

 

Endfor

 

* Set the uCommand wrapper property.

Set Com(#myscreen_wrapper) Ucommand(#com_owner)

 

Endroutine

 

* ----------------------------------------------------------------------------------------------------

* Handle Command Execution

*

* Always invoke makerampTSavailable to ensure RAMP-TS is up and running before starting a navigation

*

* You may also disable the entire form to prevent any input while RAMP is navigating

* ----------------------------------------------------------------------------------------------------

 

Mthroutine Name(uExecute) Options(*REDEFINE)

 

Invoke Method(#Com_Ancestor.uExecute)

 

Invoke Method(#myscreen_wrapper.MakeRampTSAvailable)

 

Set Com(#Save_Button) Enabled(False)

 

#com_owner.enabled := false

 

Endroutine

 

* ================================================================================

* Event Handlers

* ================================================================================

*

* RAMP has signalled it's ready. Invoke your navigation here. Also, clear the list and panel fields.

*

* Once the navigaton starts, processing resumes in the vHandleArrive event handler.

*

 

Evtroutine Handling(#myscreen_wrapper.RampTSAvailable)

 

Clr_List Named(#skills)

#XG_HEAD := *null

Invoke Method(#myscreen_wrapper.navigatetoscreen) Name('updempskills')

 

Endroutine

 

*

* The Payload is a 256 character string sent together with a SENDKEY. Use the Payload in the same way you would use parameters in an event.

* Assuming when 'updempskills' arrives we change some details and press Enter or click on the SAVE button, we expect one of these 2 screens to appear:

* If the SAVE was successfull, the INQUIRE screen appears.

* If the SAVE was NOT successfull, the update employee screen will reappear

* Setting the Payload we determine what caused the screen 'updempskills' to arrive.

*

* 1. In the Button script of updempskills for the Enter key, we attach a payload = "UPDATE_EMPLOYEE":

*

*    case KeyEnter:

*        SENDKEY( KeyEnter, "UPDATE_EMPLOYEE" )

*        break

* 2. In the ARRIVE script of INQUIRE, we test payload. If the Payload is UPDATE_EMPLOYEE this is telling us we have just done an Update and we are most likely to want to go back to the same screen.

*

*    if ( TOSTRING(oPayload) == "UPDATE_EMPLOYEE")

*    {

*       NAVIGATE_TO_DESTINATION("updempskills")

*    }

*

 

Evtroutine Handling(#myscreen_wrapper.vHandleArrive) Arrivedscreen(#CurrentScreen) Previousscreen(#PreviousScreen) Arrivedpayload(#Payload)

 

Define_Com Class(#prim_boln) Name(#MoreRecords)

 

Case (#CurrentScreen)

 

When Value_Is(= 'updempskills')

 

Set Com(#SAVE_BUTTON) Enabled(false)

 

* Payloads are destroyed when the ARRIVE script finishes executing. Therefore, a payload of UPDATE_EMPLOYEE would most likely mean there was a validation error. Otherwise - if INQUIRE had arrived - the Payload would have been destroyed.

If (#Payload = UPDATE_EMPLOYEE)

 

Use Builtin(message_box_show) With_Args(ok ok info "Validation Error" "Please correct any errors")

 

Else

* Unlock the framework - no harm done if it wasn't locked

Set Com(#avFrameworkManager) Ulocked(false)

 

 

* Get the current instance and the values of the panel fields

Invoke Method(#avListManager.GetCurrentInstance) Akey1(#deptment) Akey2(#section)

 

* If there are no entries in the list or have sent a PageDown key, get the subfile page currently on the hidden 5250

If ((#skills.entries *LE 0) Or (#Payload = NEXT_PAGE))

 

#MoreRecords := #com_owner.uGetSubfilePage

 

* There are more records in teh subfile, send a pagedown. Processing will continue in this same event handler once the same screen with the next subfile page has arrived

If (#MoreRecords)

 

#myscreen_wrapper.sendkey Key(#myscreen_wrapper.KeyPageDown) Payload(NEXT_PAGE)

 

* When all the records have been added to the list view we can re enable the panel

Else

#com_owner.enabled := true

#myscreen_wrapper.getvalue From('empno') Value(#empno.value)

#myscreen_wrapper.getvalue From('surname') Value(#surname.value)

#myscreen_wrapper.getvalue From('givename') Value(#givename.value)

#myscreen_wrapper.getvalue From('address1') Value(#address1.value)

#myscreen_wrapper.getvalue From('address2') Value(#address2.value)

#myscreen_wrapper.getvalue From('address3') Value(#address3.value)

#myscreen_wrapper.getvalue From('homephone') Value(#phonehme.value)

#myscreen_wrapper.getvalue From('postcode') Value(#POSTCODE.value)

Endif

 

Else

* We can assume that there has been a successfull update so update the instance list.

Invoke Method(#avListManager.UpdateListEntryData) Akey1(#Deptment) Akey2(#Section) Akey3(#Empno.value) Visualid2(#surname + " " + #givename) Businessobjecttype(EMPLOYEE)

 

Endif

 

Endif

 

Endcase

Set Com(#myscreen_wrapper) Visible(False)

Endroutine

 

* Traverse the skills subfile/browselist

* The technique used here consists of picking one field we know it's in the subfile, in this case "dateacq" and while there it is present on the screen, get all teh fields.

* Fields in RAMP-TS subfiles are indexed starting from 1. A subfile page with 7 rows will have 7 instances of each of the fields in the subfile. Here we increase #listcount and use it to get the value of a field.

* Note that you can specify a default value when using the getvalue method.

Mthroutine Name(uGetSubfilePage)

 

Define_Map For(*result) Class(#prim_boln) Name(#NextPage)

Define Field(#MoreVal) Type(*char) Length(1)

 

#listcount := 1

#NextPage := false

 

Dowhile (#myscreen_wrapper.check_field_exists( "dateacq" #listcount ))

 

#myscreen_wrapper.getvalue From("dateacq") Value(#vf_eltxts) Defaultvalue(#ddmmyy) Index(#listcount)

#myscreen_wrapper.getvalue From("skillcode") Value(#skilcode) Index(#listcount)

#myscreen_wrapper.getvalue From("skilldesc") Value(#skildesc) Index(#listcount) Defaultvalue("Defalt value")

#myscreen_wrapper.getvalue From("comment") Value(#comment) Index(#listcount)

#myscreen_wrapper.getvalue From("grade") Value(#grade) Index(#listcount)

 

* You can put some tracing

#com_owner.avframeworkmanager.avRecordTrace Component(#com_owner) Event("Adding entry = " + #vf_eltxts + ", " + #skilcode + ", " + #skildesc + ", " + #grade)

 

Add_Entry To_List(#skills)

 

#listcount += 1

 

Endwhile

 

* when identifying this screen we set the name of the "+" sign = "moreindicator". The presence of that field in the last row of the subfile tells us whether there is another page. The last row is one less than the current value of #listcount.

 

#listcount -= 1

 

If (#myscreen_wrapper.check_field_exists( "moreindicator" #listcount ))

#myscreen_wrapper.getvalue From("moreindicator") Value(#MoreVal) Index(#listcount)

#NextPage := (#MoreVal.trim *NE "")

Endif

 

Endroutine

 

* Listen to messages from RAMP and the 5250 application

 

Evtroutine Handling(#myscreen_wrapper.RampMessage) Umessagetype(#MsgType) Umessagetext(#MsgText)

 

 

Case (#msgtype.value)

 

When Value_Is('= VF_ERROR')

 

* Fatal messages reported by Ramp (e.g. Navigation request failed, etc). If in design mode, show the underlying 5250 screen. Otherwise, make the error message

 

* appear in a message box on top of the command

 

If (#usystem.iDesignMode = true)

 

Set Com(#myscreen_wrapper) Visible(True)

 

Else

 

Message Msgid(dcm9899) Msgf([email protected]) Msgdta(#msgtext.value)

 

#com_owner.avshowmessages

 

Endif

 

* Messages sent by the IBM i application or unknown form was encountered

 

When Value_Is('= VF_INFO' '= VF_UNKNOWN_FORM')

 

Message Msgid(dcm9899) Msgf([email protected]) Msgdta(#msgtext.value)

 

* Failure to initialize RAMP. Could occur for mainly one of two reasons

 

When Value_Is('= VF_INIT_ERROR')

 

Message Msgid(dcm9899) Msgf([email protected]) Msgdta(#msgtext.value)

 

#com_owner.avshowmessages

 

Otherwise

 

Use Builtin(message_box_show) With_Args(ok ok info *Component ('Unknown message type ' + #MsgType + 'encountered'))

 

Endcase

 

Endroutine

 

* --------------------------------------------------------------------------------

* Handle changes in any of the fields on the panel

* --------------------------------------------------------------------------------

 

Evtroutine Handling(#PanelFields<>.Changed)

 

* Enable the save button

Set Com(#SAVE_BUTTON) Enabled(True)

 

* Lock the framework and set a message for the user

Use Builtin(bconcat) With_Args('Changes made to employee' #GiveName #Surname 'have not been saved yet.' 'Do you want to save them before continuing?') To_Get(#sysvar$av)

 

Set Com(#avFrameworkManager) Ulocked(USER) Ulockedmessage(#sysvar$av)

 

Endroutine

 

* --------------------------------------------------------------------------------

* Enter key pressed

* --------------------------------------------------------------------------------

 

Evtroutine Handling(#PanelFields<>.KeyPress) Options(*NOCLEARMESSAGES *NOCLEARERRORS) Keycode(#KeyCode)

 

If Cond('#KeyCode.Value = Enter')

 

* If there no changes have been made issue message and ignore enter

 

If Cond('#SAVE_BUTTON.Enabled *EQ True')

 

Invoke Method(#Com_Owner.Save)

 

Else

 

* Issue 'There are no changes to save' message

Use Builtin(Message_box_show) With_Args(ok ok Info *Component *MTXTDF_NO_SAVE)

 

Endif

 

Endif

 

Endroutine

 

* --------------------------------------------------------------------------------

* Handle the save button

* --------------------------------------------------------------------------------

 

Evtroutine Handling(#SAVE_BUTTON.Click)

 

* Call the Save method

 

Invoke Method(#Com_Owner.Save)

 

Endroutine

 

* --------------------------------------------------------------------------------

* Handle Save

* --------------------------------------------------------------------------------

 

Mthroutine Name(Save)

 

* Set the 5250 field values to the values from this panel

#myscreen_wrapper.setvalue Infield('surname') Value(#surname.value)

#myscreen_wrapper.setvalue Infield('givename') Value(#givename.value)

#myscreen_wrapper.setvalue Infield('address1') Value(#address1.value)

#myscreen_wrapper.setvalue Infield('address2') Value(#address2.value)

#myscreen_wrapper.setvalue Infield('address3') Value(#address3.value)

#myscreen_wrapper.setvalue Infield('homephone') Value(#phonehme.value)

#myscreen_wrapper.setvalue Infield('postcode') Value(#POSTCODE.value)

 

* Send the Enter key with the payload

#myscreen_wrapper.sendkey Key(#myscreen_wrapper.KeyEnter) Payload(UPDATE_EMPLOYEE)

 

Endroutine

 

* --------------------------------------------------------------------------------

* Handle Termination

* --------------------------------------------------------------------------------

 

Mthroutine Name(uTerminate) Options(*REDEFINE)

 

* Clean up the colelction of fields on the panel

Invoke Method(#PanelFields.RemoveAll)

 

* Do any termination defined in the ancestor

Invoke Method(#Com_Ancestor.uTerminate)

 

Endroutine

 

End_Com