Pass name of field to subroutine and then refer to real field

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
User avatar
Joop
Posts: 8
Joined: Tue Dec 01, 2015 2:38 am
Location: The Netherlans
Contact:

Pass name of field to subroutine and then refer to real field

Post by Joop » Tue Jun 30, 2020 6:57 pm

Hi all,

I'm wondering if it is possible in some way to pass the name of a (repository) field to a subroutine and in that subroutine do something with the actual field (i.e. make it readonly):

Code: Select all

Execute Subroutine(Set_Field) With_Parms('GRANAV' 'Y')
Execute Subroutine(Set_Field) With_Parms('GRAHAN' 'N')

Subroutine Name(Set_Field) Parms((#FIELDNAME *RECEIVED) (#READONLY *RECEIVED))
If (#READONLY = 'Y')
   /* Make real field read only */
  #FIELDNAME.ReadOnly := True
Else
  #FIELDNAME.ReadOnly := False
Endif
Endroutine
--
Regards,
Joop Roseboom

caseywhite
Posts: 119
Joined: Thu May 26, 2016 1:17 am

Re: Pass name of field to subroutine and then refer to real field

Post by caseywhite » Wed Jul 01, 2020 2:23 am

You can't use a subroutine but you can use a method routine. You can pass in the object to a method and have the method manipulate the object. If all objects will be of the same type use the approach in umSetReadOnly2 otherwise you could use the approach in umSetReadOnly where you receive a PRIM_OBJ and then check the type to see how you will set it to read only. Sounds like in your case you can use the umSetReadOnly2 approach but wanted to show that you can do more than just pass a single class type to a method.

Code: Select all

Begin_Com Role(*EXTENDS #PRIM_WEB) Theme(#SYS_THEME<MaterialDesignBlue>)

Define_Com Class(#PRIM_MD.RaisedButton) Name(#Button) Caption('PRIMARY') Displayposition(1) Left(48) Parent(#COM_OWNER) Tabposition(1) Themedrawstyle('MediumTitle') Top(45)
Define_Com Class(#PRIM_MD.RaisedButton) Name(#Button1) Caption('ACCENT') Displayposition(2) Left(160) Parent(#COM_OWNER) Tabposition(2) Themedrawstyle('MediumAccent') Top(52)
Define_Com Class(#PRIM_MD.FlatButton) Name(#Button2) Caption('PRIMARY') Displayposition(3) Left(80) Parent(#COM_OWNER) Tabposition(3) Themedrawstyle('Borders1+BorderTheme500+ForegroundMediumPrimary') Top(161)

Evtroutine Handling(#Com_owner.Initialize)

Endroutine

Evtroutine Handling(#Button2.Click)
#com_owner.umSetReadOnly( #Button True )
#com_owner.umSetReadOnly( #Button1 False )
Endroutine

Mthroutine Name(umSetReadOnly)
Define_Map For(*INPUT) Class(#PRIM_OBJT) Name(#pObj) Pass(*BY_REFERENCE)
Define_Map For(*INPUT) Class(#PRIM_BOLN) Name(#pReadOnly)

Case Of_Field(#pobj.ComponentTypeName)
When Value_Is(= 'PRIM_MD.RaisedButton')
(#pobj *As #prim_md.RaisedButton).Enabled := #pReadOnly
Endcase
Endroutine

Mthroutine Name(umSetReadOnly2)
Define_Map For(*INPUT) Class(#PRIM_MD.RaisedButton) Name(#pObj) Pass(*BY_REFERENCE)
Define_Map For(*INPUT) Class(#PRIM_BOLN) Name(#pReadOnly)

#pObj.Enabled := #pReadOnly
Endroutine

End_Com


User avatar
Joop
Posts: 8
Joined: Tue Dec 01, 2015 2:38 am
Location: The Netherlans
Contact:

Re: Pass name of field to subroutine and then refer to real field

Post by Joop » Wed Jul 01, 2020 4:44 pm

Hi Casey,

Thanks for your input! I will try if that works for me. I was also considering using a keyed collection of fields (with the key being the name of the field).
--
Regards,
Joop Roseboom

User avatar
Joop
Posts: 8
Joined: Tue Dec 01, 2015 2:38 am
Location: The Netherlans
Contact:

Re: Pass name of field to subroutine and then refer to real field

Post by Joop » Wed Jul 01, 2020 7:35 pm

Hi Casey,

I don't think your solutions works for me. I'm using a reusable part with some fields on it. Not every user can view and/or update the fields. I wanted to make a generic subroutine / mthroutine to determine if a passed field should be read-only or visible at all. The code below does not work.

Code: Select all

Define_Com Class(#GRANAV.Visual) Name(#GRANAV) ComponentVersion(1) DisplayPosition(12) Left(16) Parent(#Panel_Algemeen_Top) TabPosition(6) Top(76) MarginLeft(120) Width(350)
Define_Com Class(#GRAHNM.Visual) Name(#GRAHNM) DisplayPosition(13) Left(16) Parent(#Panel_Algemeen_Top) TabPosition(7) Top(98) Width(350) MarginLeft(120) Height(19)

Mthroutine Name(uExecute) Options(*Redefine)
  #COM_OWNER.uSetField( #GRANAV )
  Value #GRANAV is not valid for parameter pField 
  #COM_OWNER.uSetField( #GRAHNM )
  Value #GRAHNM is not valid for parameter pField
Endroutine /* uExecute */

Mthroutine Name(uSetField)
  Define_Map For(*Input) Class(#FIELDNAME.Visual) Name(#pField) Pass(*By_Reference)
  #RMARD #RMAUPD := J
  #FIELDNAME := #pField.Name
  * Check field authority for *USER
  Fetch Fields(#RMARD #RMAUPD) From_File(ZNPRMA) With_Key(*USER *Z03_RMSTPA_C *COMPONENT #FIELDNAME)
  If (#RMARD = N)
    #pField.Visible := False
  Endif
  If (#RMAUPD = N)
    #pField.Enabled := False
    #pField.VisualStyle <= #ZVSRDONLY
  Endif
Endroutine /* uSetField */

I'm going to look into the keyed collection but not sure if that would work either.
--
Regards,
Joop Roseboom

caseywhite
Posts: 119
Joined: Thu May 26, 2016 1:17 am

Re: Pass name of field to subroutine and then refer to real field

Post by caseywhite » Thu Jul 02, 2020 1:20 am

I think you just need to change the class of the define_map in uSetField. It should be #PRIM_EVEF not #FIELDNAME.Visual. You can figure out the class to use by going to the Outline view. Right click on the fields and you will see the PRIM class for the fields is PRIM_EVEF. See the simplified code below.

Code: Select all

Define_Com Class(#STD_TEXT.Visual) Name(#STD_TEXT) Componentversion(1) Displayposition(1) Left(16) Parent(#COM_OWNER) Tabposition(1) Top(76) Marginleft(120) Width(350) Height(21) Usepicklist(False)
Define_Com Class(#STD_TEXTS.Visual) Name(#STD_TEXTS) Displayposition(2) Left(16) Parent(#COM_OWNER) Tabposition(2) Top(98) Width(350) Marginleft(120) Height(19) Usepicklist(False)

Mthroutine Name(uExecute)
#COM_OWNER.uSetField( #STD_TEXT )
#COM_OWNER.uSetField( #STD_TEXTS )
Endroutine /* uExecute */

Mthroutine Name(uSetField)
Define_Map For(*INPUT) Class(#PRIM_EVEF) Name(#pField) Pass(*BY_REFERENCE)

#pField.Visible := False
#pField.Enabled := False
#pField.VisualStyle <= #STD_VS
Endroutine /* uSetField */


User avatar
Joop
Posts: 8
Joined: Tue Dec 01, 2015 2:38 am
Location: The Netherlans
Contact:

Re: Pass name of field to subroutine and then refer to real field

Post by Joop » Thu Jul 02, 2020 4:59 pm

Hi Casey,

You are right! The class needed to be changed. Now it works.
Thanks again for your input.
--
Regards,
Joop Roseboom

Post Reply