Create a Reusable Part for the Command Handler

In the Visual LANSA editor, use File > New > Reusable Part:

 

Choose Basic Command Handler in VLF-ONE Reusable Part:

 

Give the command handler a name and description, and make the Target Platform Web Browser.

Click Create.

 

When the command handler has been opened in the editor, double-click it to display its details. Note that its ancestor is #VF_AC010O which is the common ancestor for all VLF-ONE command handlers:

 

Switch to the Source tab and replace the code in it with this code:

Begin_Com Role(*EXTENDS #VF_AC010O) Height(281) Width(513)

 

Define_Com Class(#xEmployeeIdentification.Visual) Name(#xEmployeeIdentification) Displayposition(1) Height(21) Left(23) Parent(#COM_OWNER) Tabposition(1) Top(42) Width(237) Readonly(True)

Define_Com Class(#xEmployeeSurname.Visual) Name(#xEmployeeSurname) Displayposition(2) Left(23) Parent(#COM_OWNER) Tabposition(2) Top(64)

Define_Com Class(#xEmployeeGivenNames.Visual) Name(#xEmployeeGivenNames) Displayposition(3) Left(23) Parent(#COM_OWNER) Tabposition(3) Top(86)

Define_Com Class(#xEmployeeStreet.Visual) Name(#xEmployeeStreet) Displayposition(4) Height(21) Left(23) Parent(#COM_OWNER) Tabposition(4) Top(108) Width(479)

Define_Com Class(#xEmployeeCity.Visual) Name(#xEmployeeCity) Displayposition(5) Height(21) Left(23) Parent(#COM_OWNER) Tabposition(5) Top(130) Width(479)

Define_Com Class(#xEmployeeState.Visual) Name(#xEmployeeState) Displayposition(6) Height(21) Left(23) Parent(#COM_OWNER) Tabposition(6) Top(152) Width(479)

Define_Com Class(#xEmployeePostalCode.Visual) Name(#xEmployeePostalCode) Displayposition(7) Height(21) Left(23) Parent(#COM_OWNER) Tabposition(7) Top(174) Width(249)

Define_Com Class(#PRIM_PHBN) Name(#Button_Save) Caption('Save') Displayposition(8) Left(376) Parent(#COM_OWNER) Tabposition(8) Top(216) Width(129) Enabled(False)

 

* Make pressing the enter key the same as pressing the search button

Define_Com Class(#prim_stpg) Name(#Enter) Shortcut(Enter) Parent(#COM_OWNER)

 

* The employee currently being viewed and edited

Define_Com Class(#vf_lm003O) Name(#DisplayedEmployeeDataItem) Reference(*DYNAMIC)

 

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

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

 

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

* Handle initialization

Mthroutine Name(uInitialize) Options(*Redefine)

Define_Com Class(#prim_evp) Name(#TempField) Reference(*DYNAMIC)

 

* Build collection of Editable fields

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

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

#TempField <= #Control *As #prim_evp

#PanelFields.Insert( #TempField )

Endif

Endfor

 

Endroutine

 

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

* Handle termination

Mthroutine Name(uTerminate) Options(*Redefine)

 

* Clean out any reference to the last item (very important)

#DisplayedEmployeeDataItem <= *null

 

* Clean up the collection of fields on the panel

Invoke Method(#PanelFields.RemoveAll)

 

* Do any termination defined in the ancestor

Invoke Method(#Com_Ancestor.uTerminate)

 

Endroutine

 

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

* This runs when the Details command handler is shown for an employee

Mthroutine Name(uExecute) Options(*REDEFINE)

 

* Do the ancestor thing

#Com_Ancestor.uExecute Gotofreestate(#GotoFreeState) Switchcallerreference(#SwitchCallerReference)

 

* Check for any unsaved chanegs from previous displays and

* only proceed is their is nothing that needs to be saved

If (#COM_OWNER.CheckForUnsavedChanges( False ))

* This is going to be the employee we are working with

#DisplayedEmployeeDataItem <= #AVLISTMANAGER.CurrentInstance

* Clear any messages from the previous employee

#AVFRAMEWORKMANAGER.avClearMessages Requester(#COM_OWNER)

* Get the employee data from the server

#Com_Owner.GetDataFromServer

* GetDataFromServer will release the Busy State itself

#GotoFreeState := False

Endif

 

Endroutine

 

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

* Get the Data for an employee

Mthroutine Name(GetDataFromServer)

* The locally scoped return code

Define_Com Class(#IO$STS) Name(#IOStatusReturnCode)

* Define the Server Module method routine used to get data from the server

Define_Com Class(#SModule1.Find) Name(#Find)

 

* Group of fields

Group_By Name(#DataFields) Fields(#xEmployeeSurname #xEmployeeGivenNames #xEmployeeStreet #xEmployeeCity #xEmployeeState #xEmployeePostalCode #xEmployeeHomeTelephone #xEmployeeBusinessTelephone #xEmployeeStartDate #xEmployeeTerminationDate #xDepartmentCode #xEmployeeSalary)

 

* Clear any messages

#AVFRAMEWORKMANAGER.avClearMessages Requester(#COM_OWNER)

 

* Get the data from the server by doing an asynchronous call to the Server Module DF_T42DSO

* The data is returned as the #DataFields Group of fields

 

#xEmployeeIdentification := #DisplayedEmployeeDataItem.avAKey1

 

#Find.Execute Status(#IOStatusReturnCode) Xemployee(#DataFields) Xemployeeidentification(#xEmployeeIdentification)

 

* Handle asynchronous completion of the server operation

Evtroutine Handling(#Find.Completed)

If (#IOStatusReturnCode *EQ OK)

* The data from the #datafields Group_by is displayed in the fields on the screen

Else

#AVFRAMEWORKMANAGER.avIssueMessage Text('Data not found on the Server') Requester(#Com_Owner)

Endif

* Employee has not been changed yet and is freshly display

#Button_Save.Enabled := False

* Go back to display free state

#com_Owner.avGotoFreeState

Endroutine

 

Endroutine

 

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

* Start the save

Evtroutine Handling(#Button_Save.Click #Enter.Pressed)

If (#Button_Save.Enabled)

#COM_OWNER.SaveEmployee

Endif

Endroutine

 

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

Mthroutine Name(SaveEmployee)

* The locally scoped return code

Define_Com Class(#IO$STS) Name(#IOStatusReturnCode)

* Define the Server Module method routine used to save data to the server

Define_Com Class(#SModule1.Save) Name(#Save)

* Fields to be passed to Server Module DF_T42DSO

Group_By Name(#SaveFields) Fields(#xEmployeeIdentification #xEmployeeSurname #xEmployeeGivenNames #xEmployeeStreet #xEmployeeCity #xEmployeeState #xEmployeePostalCode #xEmployeeHomeTelephone #xEmployeeBusinessTelephone #xEmployeeStartDate #xEmployeeTerminationDate #xDepartmentCode #xEmployeeSalary)

 

* Note: Clear messages in status bar otherwise old messages are too confusing

#AVFRAMEWORKMANAGER.avClearMessages Requester(#COM_OWNER)

* Indicate to the user that a save is occuring

#COM_OWNER.avGotoBusyState Showbusytext('Saving') Animated(False)

 

* Now initiate the save asynchronously

#Save.ExecuteAsync Status(#IOStatusReturnCode) Xemployee(#SaveFields)

 

* Handle the asynchronous result

Evtroutine Handling(#Save.Completed)

* Get server messages and issue them in the Framework

#avFrameworkManager.avReceiveSystemMessageQueue Requester(#Com_owner)

 

If (#IOStatusReturnCode = OK)

* Message indicating successful update

#avFrameworkManager.avIssueMessage Text('Save was successful') Requester(#COM_OWNER)

* Update the instancelist entry if required and if it still viable exists

If (#DisplayedEmployeeDataItem.avVisualID2 *IsNot *Null)

#DisplayedEmployeeDataItem.avVisualid2 := #xEmployeeSurname + ', ' + #xEmployeeGivenNames

#DisplayedEmployeeDataItem.avUpdateDisplay

Endif

* Data has been saved so no need to allows save button now

#Button_Save.Enabled := False

Else

#avFrameworkManager.avIssueMessage Text('Save was NOT successful') Requester(#COM_OWNER) Type(WARN)

Endif

* Go back to display free state

#com_Owner.avGotoFreeState

 

Endroutine

 

Endroutine

 

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

* Enable the save button when the user changes something

Evtroutine Handling(#PanelFields<>.Changed)

 

#Button_Save.Enabled := True

 

Endroutine

 

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

* Indicate back to framework whether a close operation is currently allowed

Mthroutine Name(uQueryCanClose) Options(*REDEFINE)

 

#COM_OWNER.CheckForUnsavedChanges Timeoutinprogress(#TimeOutinProgress) Allowtoproceed(#Allow)

 

Endroutine

 

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

* Returns True (Go ahead) or False (there are changes AND the user wants to save them)

Mthroutine Name(CheckForUnsavedChanges)

Define_Map For(*INPUT) Class(#prim_boln) Name(#TimeOutinProgress)

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

 

* If a save operation is pending and not timed out

If (#Button_Save.Enabled And #TimeOutinProgress.Not)

#AllowtoProceed := (#SYS_WEB.Confirm( ('Changed details of ' + #xEmployeeGivenNames + ' ' + #xEmployeeSurname + ' have not been saved. Do you want to save them first?') ) = Cancel)

Else

#AllowtoProceed := True /* Default */

Endif

 

Endroutine

 

End_Com

 

Switch to the Design tab to see the user interface of your command handler.

Compile the command handler.