ORDA: How do you access Form variables in Inherited/subforms?

Product :4D - 4D Server
4D : v17
OS : Windows

I like the new ORDA expressions and use of Form variables. However, I am not sure how to access Form variables in inherited forms or sub-forms. Can somebody point to information that shows how to?

Thanks

Subforms have a variable assigned them-self, which should be an object.

The interesting trick here is, that inside the subform, this variable can be accessed via Form.

And if the subform is really supposed to access the whole Form object from the main form, you would need to assign the content of Form to the object variable assigned to the subform. In addition, as replacement, or as part.

Hi,

May I dump this evening, but I’m not able to display an entity in a subform from a main form, to update it and to load another one this the same Subform.
For sure, I make something wrong.
Do you have an example to share or advices?

Patrick

Sorry, no example to upload. I’m using a similar scenario, just in a more complex solution, so difficult to extract.

Imagine a form, left side a large listbox, showing all records.
Left side a subform, showing details of the selected record.

The user can change the displayed table (customer, invoice, products, etc), which dynamically update the listbox on the left.

To have correct display of the details, the right area with the details is a subform, so I can assign different input forms, via:
Case of
: (Form.table=“Kunden”)
OBJECT SET SUBFORM(;“Direkteingabe”;[Kunden];“Orda_Kunden1”)
: (Form.table=“Auftrage”)
OBJECT SET SUBFORM(
;“Direkteingabe”;[Auftrage];“Orda_Auftrag”)
: (Form.table=“Rechnungen”)
OBJECT SET SUBFORM(*;“Direkteingabe”;[Rechnungen];“Orda_Rechnung”)
Else

Some detail form, such as Kunden/Customer, have several pages. Instead of switching pages I have many forms (Kunden1, Kunden2, Kunden3), where I simply assign another form to the subform instead of switching pages.

In the main form I’m using the Form object for many data, like displayed table (.table), title of the window (5 of 200 products), and more.
Form.SelectedElement is automatically managed by the list box.

Form.Direkt (sorry for the strange attribute name, not even makes much sense in German, needs refactoring, keeping here the name to allow me copy&paste) is assigned to the subform and stores all information needed to display the details.
It is an object itself, with deeper attributes.
Form.Direkt.DSatz is the current selected entityy.

Object Method of the list box (extract).
: (Form event=On Selection Change)
If (Form.Direkt.DSatz#Null)
If (Form.Direkt.DSatz.touched())
CONFIRM(“save changes?”)
If (OK=1)
C_OBJECT($status)
$status:=Form.Direkt.DSatz.save(dk auto merge)
Case of
: ($status.success)
// all is fine
: ($status.status=dk status automerge failed)
ALERT(“somebody else has changed the same fields, your modifications cannot be saved!”)
: ($status.status=dk status locked)
$user:=$status.lockInfo.user_name+"/"+$status.lockInfo.host_name+"/"+$status.lockInfo.task_name
CONFIRM("record locked from "+$user;“wait”;“cancel”)
If (OK=1)
Form.SelectedElement:=Form.Direkt.DSatz
Else
End if
End case
End if
End if
End if
Form.Direkt.DSatz:=Form.SelectedElement
EXECUTE METHOD IN SUBFORM(“Direkteingabe”;“Orda_Listbox_subformMethod”)

When the current selected record changes, I’m checking if there are modifications needed to be saved - and handling record locking/collisions as well.
If all is fine, I assign the new entity.

Finally I execute a method inside the context of the subform, to update the details.

For all tables this is doing something as:
Case of
: (Form.table=“Kunden”)
Form.Kunde:=Form.DSatz

depending of the table, more fields are set, Popups are filled, objects are enabled/disabled, etc.
Form.Customer.Name or Form.Invoice.Date is easier to read in the form or form method as a generic name, that’s why I assign that. Remember, that’s not a copy, no memory wasted, just a reference…

Note that in the subform, there is another Form object (of the subform, not of the main form)
In the main form I have assigned Form.Direkt
The Subform receives its own Form object with the content of the main form’s Form.Direct attribute.

The form (assigned to the subform) is using variables to display the data via Form.Kunde.name ([Kunde]name)

Now back to the start. When user changes the selection of the list box (click on another line), I check if data was changed, needs to be saved, then assign the new selected line, call the subform, which assign it to my attribute, which triggers are redraw…

Sounds more complicated as it is. But works (surprisingly) simple and allows an user interface design not possible before…

It was not created for demo/training purposes, I wrote the code when learning ORDA.
And yes, attribute names do not follow best practice.
The database/structure is 30+ years old, I would use very different naming and coding style if I could redevelop from scratch.

: Thomas MAUL

Sorry, no example to upload. I’m using a similar scenario, just in a
more complex solution, so difficult to extract.
Don’t be sorry !

Thanks a lot for all your explanations. I’ll try to adapt your scenario to mine and let you know.
If i’m able to share an example, I will.

Patrick

Very interesting, thanks a lot…

: Thomas MAUL

Some detail form, such as Kunden/Customer, have several pages.
Instead of switching pages I have many forms (Kunden1, Kunden2,
Kunden3), where I simply assign another form to the subform instead
of switching pages.

Why did you choose to do like that (I’m not familiar with subforms, maybe it’s not possible to have multiple pages in a subform ?). So when switching page and subform, you need to reload everything, including every change the user is currently doing !?

: Eric TROTTA

Why did you choose to do like that

It started with a customer issue.
He had a form with 30+ pages. Some 4D Write, some 4D View, several Web Areas and many 4D forms.

All worked ok. A little bit slow, sometimes a little bit spooky, but ok.
Except, when an user was nervous and clicked very fast next/previous record buttons.
Then everything got mad - sometimes.

we analyzed and realized that in this situation several plugin on load and on unload (4D Write/View) was executed at the same time. In parallel several web areas tried loading or tried accessing not existing content anymore.
All was depending on the speed of the PC, speed of network and good/bad luck.

Not the best combination for a serious business application.

The issue was not enough control about too many parallel actions.
And it made absolutely no sense to load/prepare many plugins or web areas which was never used anyway.

By strictly having only subforms with exactly ONE page, absolute control was reached. Only one page was loaded - only one page was displayed. Not needed parts was not initialised. No time wasted.

When I realised the benefits, I started to change my own apps.

And no, you do not need to load anything (as long we talk about fields from the same record). If you display on page 25 records from another table, never displayed before, then load them only when page 25 is displayed…
Of course you edit data from many tables you need a transaction, but that’s the same with all in the same form.

When you used so far a tab control with an object code doing GOTO PAGE, you just replace that with OBJECT SET SUBFORM, such as:

: (mytabcontrol=6)
	OBJECT SET SUBFORM(*;"SubFormContainer";[Kunden];"Input_06_Mailing")

In the On load of the displayed form you might want to load more data, such as build a selection for a list box, prepare button status, etc.

But reminder, this is not necessary, it is only a possible approach if you have a multi page form, especially with many complex subforms. It produces cleaner code, and as less code is executed, everything usually is faster.

Very surprising and interesting… Thanks a lot for all these details !