Home › Forum › Omnis General Forum › SubForms
-
SubForms
Posted by kevin on July 30, 2025 at 5:53 amI have a remote form with two subforms (along with other objects such as a results list displaying the results of the search) : –
a. subform1 displaying a list of consultants (used for searches), and
b. subform2 displaying the details for the line that the user has selected in the results list (not a subform).
Both subforms are embedded in a tabbed pane.
Tab 1 has the consultant subform and tab 3 has subform 2. Tab 2 displays the result of the search.
When the remote form opens I can get a reference to the consultants subform via: –
set reference to iIRConsultantssw to $cinst.$objs.swUserSearch.$subinst()
However, try as I might, I cannot get a valid reference to the subform on the 3rd tabpane
I asked ChatGPT and I was advised that Omnis Studio does not cater for more than one current subform.
ChatGPT recommended using the following code to reference the 2nd subwindow:
Calculate $cinst.$form.$currentsubform as $cinst.$form.$subform2
However, this does not seem to work.
My goal is to have the subforms visible/instantiated once but when the user clicks on a line (in the results list on the 2nd pane) I want to pass that row to the subform and have the subform refresh with the target details. I want to repeat this process each time the user clicks on a different line.
Is this possible?
What am I doing wrong?
I have the multipleclasses turned OFF for the subforms
I set the class name for both subforms at design stage.
Andreas Pfeiffer replied 2 weeks, 3 days ago 2 Members · 8 Replies -
8 Replies
-
Hi Kevin,
I assume the subform on the next page is not instantiated yet when you are trying to send a message. Therefore you will not be able to get a reference to that instance. Only when the page will become visible it will create the instance inside the subform field.
My advice is to get rid of the page pane and use one subform that loads the data itself. Add a control (i.e. tab strip) that simply assigns the $classname of the subform. Every time you do this its $construct will be executed and from there you can call a method in the main form to get information from it and rebuild its own data. Note that $multipleclasses needs to be kFalse. Otherwise the instance will stay alive and you cannot rely on having its $construct executed when the the $classname is assigned.
You may want to check out the contacts web application sample library that I posted in this forum. It uses this technique. It does use a paged pane. However there is only one sub window on page two and this one gets dynamically assigned.
Hope this helps.
Best regards,
Andreas
omnis.net
Contacts Web Application - Omnis Forum
This is the Contacts Web Application created as a demo version for the Madagascar ODC event. You can download and run it with the Omnis…
-
Hi Andreas,
Thank you so much for your insight and quick response (as always).
So, to summarise, Omnis Studio: –
* Does not cater for more than one active or current subform at anytime
* Does not permit you to change the current subform
* constructs subforms AFTER the main form has been instantiated (the reverse of desktop equivalents).
I was hoping to approximate the behaviour/appearance of equivalent desktop windows and subwindows.
I use subwindows and subforms where there is a need to display the same data in different situations – without having to duplicate the window/remote form in each case. Standard stuff I believe.
I ran some tests by creating a tabpane on a simple remote form and placing a (different) subwindow on each and tried to set a reference to each subform using $subint. I discovered that I could set a reference to the subform on the 1st pane by default. However, I could not get a valid reference to the pane until after the 2nd pane had been opened.
Once the 2nd pane had been opened I could then set a valid reference to the subwindow (using $subinst). Furthermore, the reference to the 1st subform seems to persist. This is what I was looking for. I will have to run some more tests to check the downstream results.
This then leads to how to use $loadfinished. It is not clear how or when you use this method. Do we have to call this method repeatedly until we get an answer? Do we over-ride it and set a flag of our own? For instance, after opening the 2nd pane (and thereby instantiating the subform on that pane) how do I invoke $loadfinished to know when it is OK to set a reference to the subform?
I know this is not in line with your suggestion but I would like to explore this methodology to see if it is viable – unless you have already been down that road and discovered a dead-end.
Once again thanks for your valuable advice.
Kevin
-
Hi Kevin,
very well spotted. Yes Omnis Studio allows you to have multiple subforms on a form and you are able to address them from outside once they are constructed. For performance reason the subform on the pages that are initially not visible are constructed once they become visible the first time.
You could check if the instance is there using a $cando property on the method. For example:
If $cinst.$objs.sub.$subinst().$load.$cando
Do $cinst.$objs.sub.$subinst().$load(myID)
End ifThe $loadfinished is not something you would call. This method is automatically executed once all subforms have been loaded. The problem you face here is that it won’t be executed until you make all subforms become visible – meaning you would need to change the paged pane. You can see $loadfinished like the $construct. You override it and then this code will be executed once all subforms are loaded. It would be much easier if you do not control the behaviour from the outside of the subform. Let the subform do its own job. Once it becomes constructed it could call a method in the container form.
Btw. this difference behaviour of the remote classes did lead me into slightly different development paradigm and in return it led me change my development style for fat client windows as well. I discovered that it is much more OO when bringing the power to the subwindows/forms rather trying to control everything from the outside.
I hope this helps you.
Best regards,
Andreas
-
Hi Andreas
Once again thank you for your prompt and insightful response.
I was fully prepared to have to change my coding methodology once I started working with JS forms. My problem is that I don’t know what I don’t know and I am having to experiment and feel my way forward and in doing so I am afraid that I will end up in a dead-end because of a lack of understanding at the outset.
Ideally, I would love to adopt an existing framework or to spend time with an expert in this to accelerate the development time – especially at the outset. The Omnis Conferences are timed badly right now and even then the conference is probably not the right place for my queries.
One of my experiments is to have a ‘static’ navigation tab in the browser and then , when the user clicks on a button in the navigation pane, a separate ‘working’ pane is opened (in the browser) and all necessary remote form/subform opening associated with the selected button would then be performed in that working pane. This, COULD permit the user to have multiple records open simultaneously?? Of course, the user would be prevented from editing any record that is currently being edited by another user (which could be them in a different session). In this scenario I am looking at populating a row in the Navigation pane with some necessary ‘static’ data (e.g. user ID) and then passing this data to the 2nd tab in the browser. However, this may not be practical/permissible or simply be too unwieldy. I saw a reference to $userinfo somewhere and I suspect I may have to use this in my scenario because I can’t see how to reference a different pane in the browser.
The other (simpler?) approach would be to confine all activities to a single browser pane.
Any advice O wise one? -
Hello Kevin,
For navigation my advice would be to use a main remote form that has i.e. a navigation menu bar, or something like that. That element gets $edgefloat = kEFPosnMenuBar. In addition there is only one more component, that is on single subform with $edgefloat = kEFPosnClient. That means it will take the rest of the space completely for the working area. The navigation control simply assigns the $classname of the subform control. This is for the part of navigation of an Omnis JS app. That way the user can simply navigate between different modules of your application.
Each form that is shown inside the main subform component then should act by its own and can also use subforms. Whenever those subforms need to talk to its container form you can use $cinst.$container to reference the outer form and get i.e. the ident from the container in order to fetch the data for the subform. This part is very much as in the sample library I pointed to. For example:
Do $cinst.$container().$getIdent() Returns myIdent
Do iDataList.$load(myIdent) ## if you have a $load in your table class that can deal with the identThere are not many cases why one would use task variables. I only have two in my applications. One is the session object and the other one is a user object. Use this object for the logon remote form and hold any user information within that object. BTW. the logon remote form would then use
$ctask.$changeform('jsMain')
to switch to the main navigation form. The object should then have $get… methods that may return the user id, user name etc. whenever required.
For example you could have overridden the $insert method of your super table class and then use the user object to put the user id into a certain field of your table:
i.e. Calculate $cinst.user_id as tUserObj.$getIdent()
To make it clear: every class, field etc. has a $userinfo property which is simply a property to store any data. So not really useful in that context you described.
If you need more assistance please contact your local sales rep. Omnis Software is happy to offer you consulting/training to help you getting on the right track.
I hope this helps.
Best regards,
Andreas
-
Thanks Andreas
Yes, I already figured out or knew much of what you are talking about.
For instance I am using object references that I pass from instance to instance as needed.
In a nutshell, you confine all web stuff to a single browser pane and substitute the target remote forms as needed. In this case, we will obviously need a home button on all remoted forms to allow the user to return to the main home page and thus navigate to other modules and/or forms. Logical.
Once again, thank you for your sage advice. You really do go above and beyond …
Cheers
-
Kevin,
No worries. I am glad to help.
Yes, in a sense the application is a single page application. However sometimes (i.e. printing result, prompts) I use modal forms with the client command “subformdialogshow”. For example:
Do $cinst.$clientcommand("subformdialogshow",row('jsPrint', etc.))
Also a word about record locking. This is something you’d better avoid. Always keep in mind that a connection can break and therefore the lock on the record will stay there forever.
In practice it is very seldom that two users work on the very same record. And if so you could alert them when hitting the “save” button (“record has been modified 2 mins ago, do you want to override or re-load it?”). So I wouldn’t worry much about it. I also have all my forms always in enter data mode which is much more up-2-date behaviour than the old “prepare for” stuff.
Best,
Andreas
-
Kevin,
and yes – you would need a home button. Although the home is just a page that more or less does not have much content. It is more or less the landing page that is show after the user logged on.
For example you could have a container (page pane) that has $edgefloat = kEFPosnToolbar and inside the container you have your menu and the home button. I pretty much have it this way. The home button is also when the user clicks on the logo svg icon that sits inside that container on the left side.
Best,
Andreas
Log in to reply.