If you only need the file to be available to a particular app then open that app and add the file via the Apps Workspace. If you want it available to multiple apps then put it in the Lianja Library (via the Library Workspace).
You will still have access to your App’s custom library/libraries.
You can use SET PROCEDURE TO <lib> ADDITIVE for multiple extra procedure/function libraries. The ADDITIVE means that it is opened in addition to any existing libraries.
The LIST PROCEDURE command will list the procedures and functions that are currently defined.
If it is a standalone prg, just click the + button at the bottom of the ‘Files’ in the Sidebar in the Apps Workspace and it will prompt you for the filename. The default file extension is ‘.prg’. Yes, it will be available for the whole App. When you Deploy, it will be deployed as a .dbo (pseudo-compiled) file.
If you have lots of functions you want to use, you can put them in a function/procedure library (create this using the + button as before):
Then use set procedure to <lib> additive in a delegate called before the function is required, for example in the app.load() or the app.ready() (or a delegate for the relevant Page or Section).
you can add functions (‘anotherfuncstill’ here) in with the event delegates. The custom libraries for event delegates (created when you create your first delegate) are opened for you automatically; there is no need to use set procedure in this case.
Pages and Sections can also have a ‘Valid When’ event delegate called after the field validation.
It’s handling the SET PROCEDURE correctly if the procedure library is in the App itself – it correctly loads the dbo. If the procedure library is in the Library, it is still expecting to find the prg.
If you copy the prg files into the deployed library, or the dbo files into the deployed App, this will work around it until it gets fixed.
Yes, if it’s a procedure in a procedure library you need a
set procedure to <prgfile> additive
unless it is defined as the ‘Custom Library’ for the App, a Page or a Section, in which case that will be issued for you automatically.
How can I use a variable within several procedures in the same prg file?
Remember that the section or page custom library where you define your event delegate procedures is a library, not a program that you are running from start to finish. The library declares your procedures, it doesn’t call them, so it’s not the same as one program/procedure calling another with the called procedure having access to the calling procedure’s private variables, e.g. a private variable set in Gamesheet_GSHeader_field82_click would be accessible to set_value as it is called by Gamesheet_GSHeader_field82_click.
To make a variable accessible to the procedures within your library, you do need to make it public. As Dave says, you could use a namespace to avoid conflicts. As I mentioned in a previous post, you can access public variables declared in a namespace with namespace.variable. You can also access them with just the variable name if your procedure is in the same namespace. For example:
// lib_Gamesheet_gsheader.prg namespace gsheaderpublic testmsg = "Blank" proc set_value() namespace gsheader testmsg = "testing" messagebox("Set Value message " + testmsg) messagebox(priv1) // private variable in calling procedure endproc //////////////////////////////////////////////////////////////// // Event delegate for 'click' event proc Gamesheet_GSHeader_field82_click() namespace gsheader // not currently required as does not use namespace public vars private priv1 = "Hello" // accessible to set_value set_value() endproc //////////////////////////////////////////////////////////////// // Event delegate for 'click' event proc Gamesheet_GSHeader_field83_click() namespace gsheader messagebox(testmsg) endproc
I could then have the same variable name in another page in another namespace, e.g.
//lib_page1_section1.prg namespace section1public testmsg = "This is section 1" //////////////////////////////////////////////////////////////// // Event delegate for 'click' event proc page1_section1_field78_click() namespace section1 messagebox(testmsg) endproc
I just meant design or at least complete the design with the UI Page in another App, so that you don’t have 2 copies of the same Page and controls in the main App as (from experience[IMG]file:///C:/DOCUME~1/Kruno/LOCALS~1/Temp/enhtmlclip/Image(2).png[/IMG]) that can be confusing. Once the Page is saved to the Page Library (yes, click the icon as Herb says to save it manually) it will be called from the Page Library, it just needs to be in an App too if you want to modify it. Herb’s other instructions are for code called by the UI Page. The code can either reside in the main App or in the Library. If you want it in the Library, add the ‘lib:/’ prefix as Herb says and add the relevant prg scripts to the Library.
How to call one the same page from two different applications? Calling completely including a left bar, right bar. Of course I can copy the page, but this is not correct because of maintenance at 2 locations.
You can include the Left and Right Sidebars in a Page saved to the Page Library, they just need to be set to be shown in the Page Attributes
how I can have multiple functions in one file.
Put your app specific functions in the custom library file for the app. Put your page specific functions in the custom library for the page. Same goes for section specific functions.
While you are developing and testing that is the case. The class libraries will not be automatically reloaded if the source file is edited.
In the App Builder itself, it listens for any custom libraries or other relevant files being edited and automatically recompiles and reloads them.
This in fact is how a lot of the “live” development is accomplished.
Try using SET CLASSLIB rather than SET PROCEDURE and omit the file extension.
Although set procedure will handle class definitions it is better to use set classlib.
set classlib to formclasses list classlib list classes
will show you what classes are in scope.
set procedure to mylibrary list procedure
will show you what procedures and functions are in scope.
useful functions to be aware of:
? function_exists("myprocname") ? class_exists("myclassname")
So in your code:
proc openLibs() if not function_exists("myfunc") set procedure to myfunclib additive endif if not class_exists("basebutton1") set classlib to formclasslib additive endif // etc... endproc
Which takes care of a lot of messing about with determining if a class library has been loaded or not. The classes are however declared at the current scope level and will be released when the proc returns.
If you are using these classes in a modal form then they will remain in scope until the form is closed. e.g.
// myform.prg require_once("alan.scp") loForm = createobject("myform") loForm.show(1) // blocks execution until the form is closed.
Once you have satisfied yourself that your UI forms and classes are working, you can embed them in a “Custom” section. See below.
Custom libraries are loaded internally and are not affected by SET PROCEDURE TO in any way at all.
This is another reason why I recommend their use.
No I’m referring to the custom library for the App itself.
Go into App settings.
Scroll down the attributes to the delegates.
There is a custom library that gets automatically created if you create an init, load, ready, unload, inactive delegate.
Editing that custom library lets you add your own functions.
There is a custom library for each App, Page and Section. That’s where the delegates live.
Custom libraries are automatically opened when the App is loaded. They are monitored for changes for you and recompiled and reloaded. This is a fundamental part of the Lianja App Builder development cycle. There is no explicit compile or build required.
My recommendation would be to place these functions in the App custom library rather than an external library loaded with SET PROCEDURE TO.
Why? Because lianja knows when any of these files have been edited and automatically recompiles and reloads them. That is not the case with SET PROCEDURE TO. This is exactly what happens when you edit your delegates, custom section code or ,rsp files that generate dynamic WebView content too. There is no compile and build steps required. It is done for you as the whole App is live. The UI knows when files have changed.
Also an advantage to this approach is that it is scripting language independent.
Note also that if you must use SET PROCEDURE TO you can check to see whether the library is already loaded by looking for a “well known function” in the library e.g.
if not function_exists("__mylib__") Set procedure to mylib additive // inside mylib.prg declare an empty function called __mylib__ Endif
// alternatively use require_once() which does all the hard work for you
I realise that sometimes, my changes will not take effect if I run the app immediately after making the changes
I need to load another app and reload back my original app.
May I know if there is a better way to force a refresh so that when I run the app, it will take the latest source files?
If you are using custom libraries these will automatically be recompiled and reloaded if they are edited.
If you have libraries that you are using that Lianja knows nothing about then you will need to save and reload your application for these to take effect.
In Lianja “Procedure libraries” can contain:
Procedures and Functions are essentially the same thing. It’s good practice to use “Function” if it returns a result and “Procedure” if it does not. It’s all down to personal taste.
Script files (.prg) are opened and closed every time you call them. Not a good idea for your own functions. The file should just contain the code.
//myfunc.prg return "Hello world" //mylib.prg function myfunc() return "Hello world"
I have no problem defining multiple functions in libraries but I cannot see how to call these directly from attributes (without having an intermediate prg file as per my first post)
Just edit a custom library, add your function and specify it in an expression:
and in a custom library:
function myfunc() // your code endfunc
Custom libraries are always opened when your app is opened.
When you edit a custom library Lianja detects that it has changed and will reload it automatically and compile it.