Invoke #AVFRAMEWORKMANGER.avSwitch from a Non-command handler reusable part?

This Q&A forum allows users to post and respond to "How Do I Do ....." questions. Please do not use to report (suspected) errors - you must use your regional help desk for this. The information contained in this forum has not been validated by LANSA and, as such, LANSA cannot guarantee the accuracy of the information.
Post Reply
Mkolbe
Posts: 27
Joined: Tue Apr 04, 2017 12:45 am

Invoke #AVFRAMEWORKMANGER.avSwitch from a Non-command handler reusable part?

Post by Mkolbe »

I have a reusable part that exists in several different command handlers. The resuable part acts as a common "header area" for the various command handlers. I attempted to add a button in this reusable part that when clicked, would perform an avSwitch to initiate a filter associated with an entirely different business object (see code at bottom).

However, when I attempted to run it I received an error,
"Fatal Error: Cannot read property 'mthAVSWITCH' of null
Location: Reusable Part: OC_RP_Command_OppHeader, line 382
Call Stack: 1. Evtroutine Handling(#LocButton.Click): OC_RP_Command_OppHeader, line 382
Reported By: oc_rp__2.js, line 4088:38"

After reading the Lansa documentation on the use of avSwitch, I'm wondering if I can even do this? Can the avSwitch only be initiated by true command handlers?

http://docs.lansa.com/14/en/lansa048/in ... Ref4558516 -
"This service allows your filters and command handlers to switch control between different business objects and to execute commands at the Framework, application or business object level.The switching service is invoked by using method #avFrameworkManager.avSwitch with the appropriate parameters. "

** CODE IN NON-COMMAND HANDLER REUSABLE PART.
Evtroutine Handling(#LocButton.Click)
#AVFRAMEWORKMANAGER.avSwitch Caller(#COM_OWNER) Toobjectnamed(LOCATIONS)

#Timer1.Interval := 1000
#Timer1.Start

Endroutine

Evtroutine Handling(#Timer1.Tick)

#Timer1.Stop

* Initiate the Location Filter reusable part and cause it to display the Location for this opportunity.
* The "To" parameter should be "APPLICATION" (rather than "BUSINESSOBJECT") in this case because we want to signal this event to the OPPORTUNITY BUSINESS
* OBJECT and NOT the Business object that this command handler is associated with (Locations).
* See "avEvent" Event routine in the Location Filter reusable part.
#COM_OWNER.avSignalEvent Withid(OneLoc) To(APPLICATION) Sendainfo1(#OC01_Company) Sendainfo2(#OC01_LocationID)
#COM_SELF.avCloseForm

Endroutine
Image
Attachments
Lansa - avSwitch button in Reusable Part.JPG
Lansa - avSwitch button in Reusable Part.JPG (43.46 KiB) Viewed 10929 times
jyoung
Posts: 694
Joined: Thu Jan 21, 2016 6:43 am
Location: Oklahoma City, OK USA

Re: Invoke #AVFRAMEWORKMANGER.avSwitch from a Non-command handler reusable part?

Post by jyoung »

I think the "Fatal Error: Cannot read property 'mthAVSWITCH' of null" error is telling you your avFrameworkManager is null.

You mention your "header area" is not an actual command handler. How are you getting access to it? If you simply inherited from VF_AC010O then I don't think it will be initialized property. This is something you will need to do in your command handler in the uInitialize method.

Another option would be delegate the switch to your actual command handlers where the FrameworkManager is already initialized. Simply expose an event from your Reusable Part and signal it on the button click. Then your command handler can listen for that event and issue the switch.
Mkolbe
Posts: 27
Joined: Tue Apr 04, 2017 12:45 am

Re: Invoke #AVFRAMEWORKMANGER.avSwitch from a Non-command handler reusable part?

Post by Mkolbe »

The command Handler in question is named "OC_RP_Command_Sales". It (along with several other command handlers) references my reusable part, named "OC_RP_Command_OppHeader", that contains the header fields. I included another screen shot below.

Command Handler "OC_RP_Command_Sales"
Begin_Com Role(*EXTENDS #VF_AC010O) Layoutmanager(#Layout2) Width(1000) Height(657) Horizontalscroll(True) Verticalscroll(True) Imagealignment(TopCenter)
.
.
Define_Com Class(#OC_RP_Command_OppHeader) Name(#HeaderInfo) Displayposition(9) Parent(#COM_OWNER) Tabstop(False)
.
.

Reusable part "OC_RP_Command_OppHeader"
Begin_Com Role(*EXTENDS #VF_AC010O) Height(153) Width(1089) Layoutmanager(#Layout3)
.
.

I was hoping that my issue was purely within the OC_RP_Command_OppHeader reusable part, so that I wouldn't need modify all the command handlers that use it (e.g. when you wrote... "Another option would be delegate the switch to your actual command handlers where the FrameworkManager is already initialized. Simply expose an event from your Reusable Part and signal it on the button click. Then your command handler can listen for that event and issue the switch.") But maybe the command handlers are missing something I need to add?

I looked at another entirely unrelated Command Handler and it has the following in the uInitialize Method routine:
Mthroutine Name(uInitialize) Options(*REDEFINE)
#AVFRAMEWORKMANAGER.avRestoreValue Toavalue(#OC01_Company) Withid1(*COMPONENT) Withid2("COMPANY")
#Com_Ancestor.uInitialize

Is this the type of thing you were referring to when you wrote, "If you simply inherited from VF_AC010O then I don't think it will be initialized property. This is something you will need to do in your command handler in the uInitialize method."?

Lansa - OC_RP_Command_Sales.JPG
Lansa - OC_RP_Command_Sales.JPG (108.29 KiB) Viewed 10909 times
jyoung
Posts: 694
Joined: Thu Jan 21, 2016 6:43 am
Location: Oklahoma City, OK USA

Re: Invoke #AVFRAMEWORKMANGER.avSwitch from a Non-command handler reusable part?

Post by jyoung »

Your OppHeader extends #VF_AC010O, which is the command handler base. However, since your OppHeader component is not directly tied into the framework, its not going to get some of its properties initialized, specifically the FrameworkManager.

Edit Meaning that your register OC_RP_CommandSales in the Workbench, not your OC_RP_Command_OppHeader.

You need to initialize it yourself in your OC_RP_CommandSales.
Something like this:

Code: Select all

mthroutine name(uInitialize) options(*REDEFINE)
* Do ancestor first
#COM_ANCESTOR.uInitialize
* Custom code here ....
#OC_RP_Command_OppHeader.avFrameworkManager <= #avFrameworkManager
endroutine
The key thing to remember, is that the command that gets initialized is the command(s) that are defined in the Workbench. If you create your own components, even if you extend the VLF objects, you have to pass the initialization along yourself.

You can avoid all that by using a pure VL Web component for your header.
For example, you can make a panel (extends PRIM_PNL)

Code: Select all

begin_com role(*EXTENDS #PRIM_PANL) displayposition(1) height(270) left(0) tabposition(1) top(0) width(500)

define_com class(#PRIM_PHBN) name(#Button1) caption('Button1') displayposition(1) left(187) parent(#COM_OWNER) tabposition(1) top(115)

define_evt name(ButtonClicked)
* use define map to specifiy event parameters

evtroutine handling(#Button1.Click)
signal event(ButtonClicked)
endroutine

end_com


Drag that panel on your command (like before) and then you can "subscribe" to the ButtonClicked event, and do the switch there:

Code: Select all

begin_com role(*EXTENDS #VF_AC010O) layoutmanager(*NULL) width(425) height(313)
define_com class(#PRIM_LABL) name(#Label1) caption('Content') displayposition(1) ellipses(Word) height(25) left(136) parent(#COM_OWNER) tabposition(1) tabstop(False) top(248) verticalalignment(Center) width(120)
define_com class(#JRYTestHeaderPanel) name(#JRYTestHeaderPanel) displayposition(2) left(88) parent(#COM_OWNER) tabposition(2) tabstop(False) top(48)

* --------------------------------------------------------------------------
mthroutine name(uInitialize) options(*REDEFINE)
* Do ancestor first
#COM_ANCESTOR.uInitialize
* Custom code here ....
endroutine

* --------------------------------------------------------------------------
mthroutine name(uTerminate) options(*REDEFINE)
* Custom code here ....
* Do ancestor last
#COM_ANCESTOR.uTerminate
endroutine
* --------------------------------------------------------------------------
mthroutine name(uExecute) options(*REDEFINE)
* Do any ancestor logic first.
#COM_ANCESTOR.uExecute gotofreestate(#GotoFreeState) switchcallerreference(#SwitchCallerReference)
* Custom code here ....
endroutine

evtroutine handling(#JRYTestHeaderPanel.ButtonClicked)
#AVFRAMEWORKMANAGER.avSwitch caller(#COM_OWNER) toobjectnamed(MY_OTHER_OBJECT)
endroutine
* --------------------------------------------------------------------------
end_com
- Joe
jyoung
Posts: 694
Joined: Thu Jan 21, 2016 6:43 am
Location: Oklahoma City, OK USA

Re: Invoke #AVFRAMEWORKMANGER.avSwitch from a Non-command handler reusable part?

Post by jyoung »

One of the issues I ran into doing something similar was that I did not have access to the FrameworkManager when I needed it, for example in a shared component.

One way that I deal with it is that I have an application scoped object that is shared across my objects. Then I have a Framework IIP that initializes the FrameworkManager. Then all I have to do, is include my object (in application scope) and I have the framework.

Example:
Here is the scoped object, what I call my "ApplicationManager"

Code: Select all

begin_com role(*EXTENDS #PRIM_OBJT)
* ================================================================================
* COMPONENTS
* ================================================================================
define_com class(#VF_SY100O) name(#avFrameworkManager) reference(*DYNAMIC)

* ================================================================================
* PROPERTIES
* ================================================================================
define_pty name(avFrameworkManager) get(*REFERENCE #avFrameworkManager) set(*REFERENCE #avFrameworkManager)

* other stuff omitted
end_com
Then I have a SystemIIP that sets the avFrameworkManager reference

Code: Select all

begin_com role(*EXTENDS #VF_AC011O)

* define ALL application managers
define_com class(#CMGApplicationManager) scope(*APPLICATION)

* -----------------------------------------------------------------------------
* Initialzie and setp up values
mthroutine name(uInitialize) options(*REDEFINE)

* Do the ancestor default behaviour
#COM_ANCESTOR.uInitialize

* set the application managers, framework manager
#CMGApplicationManager.avFrameworkManager <= #avFrameworkManager

* Use a single shared message set in tablet mode
#SharedMessageSetinTabletMode := true

endroutine

* other stuff omitted
end_com
Register the IIP in the Workbench (Framework Details Tab)
capture.PNG
capture.PNG (6.93 KiB) Viewed 10906 times
Then to use the ApplicationManager, simply include it at application scope

Code: Select all

define_com class(#CMGApplicationManager) scope(*APPLICATION)

mthroutine name(DoSomething)
#CMGApplicationManager.avFrameworkManager.avSwitch caller(#COM_OWNER) toobjectnamed(MY_OTHER_OBJECT)
endroutine
Mkolbe
Posts: 27
Joined: Tue Apr 04, 2017 12:45 am

Re: Invoke #AVFRAMEWORKMANGER.avSwitch from a Non-command handler reusable part?

Post by Mkolbe »

The easiest change for me to make was to add the one line of code to each command handler to pass the Framework info to the reusable part that they all shared.

#OC_RP_Command_OppHeader.avFrameworkManager <= #avFrameworkManager

From within the one reusable part containing my header info and button, I was able to perform the avSwitch and signal an event that my location filter was expecting.

#AVFRAMEWORKMANAGER.avSwitch Caller(#COM_OWNER) Toobjectnamed(LOCATIONS)
#COM_OWNER.avSignalEvent Withid(OneLoc) To(FRAMEWORK) Sendainfo1(#OC05_Company) Sendainfo2(#OC05_Location)

Thanks for responding.
MarkD
Posts: 692
Joined: Wed Dec 02, 2015 9:56 am

Re: Invoke #AVFRAMEWORKMANGER.avSwitch from a Non-command handler reusable part?

Post by MarkD »

Using your own custom framework manager has to a large extent superseded the VLF's event signalling service.

Refer to note at the start of this documentation - http://docs.lansa.com/14/en/lansa048/in ... 8_0850.htm

and also http://docs.lansa.com/14/en/lansa048/in ... f437604740
Post Reply