Tools
Sign in
Login
Forum
Remember Variables
Forum
>
Business Object Composition
>
Remember Variables
n/A
posted
on July 24, 2013
at 2:46 PM
n/A
posted
on July 24, 2013
at 2:46 PM
I could not find any documentation of the
Remember Variables
screen feature. Could you please refer me to some documentation or explain how it works?
Stephan
replied
on July 25, 2013
at 4:43 PM
Stephan
replied
on July 25, 2013
at 4:43 PM
Hi Biƶrn,
This feature has an effect only if it is set on screens used as include or template in other screens. If you set it on a "main screen" (a screen referenced by a screen task in a process), it has no effect.
Remark: Everything written from now on about included screens and the Include screen component is equally true for screens used as templates and the Template screen component.
"Function Call" Metaphor
The screen components Include and Template work like function calls. If you call a function, you usually can pass arguments for the function's parameters. The function can have local variables defined and visible only within the function implementation. And it may use global variables defined in a higher context. Included screens work very similar. You can think of assigned variables as parameters for which you can assign a value (function arguments) at runtime. And the screen can have local variables which are similar to local variables of a function, and inherited variables which are similar to global variables of a function.
If the main screen is rendered and Appway detects an Include, it first fetches the referenced screen. It now has to "call" this screen in order to render the HTML code of the components inside this screen. It first has to initialize the variables in the target screen. In Appway, such a set of variables defined by a screen or process is called a "scope". So before the included screen can be rendered, Appway has to generate and initialize a scope for this screen.
Scope Initialization
Appway goes through all variables defined in the included screen.
If a variable is defined as
"assigned"
, it checks if there is a variable assignment expression defined in the main screen (the "caller"). If this is the case, the expression is evaluated and the result is used as initial value for the variable inside the included screen. If there is no variable assignment expression, the variable is treated like a local variable (see below).
If the variable is defined as
"inherited"
, Appway checks if the variable exists in a parent scope (main screen or process). If it exists, Appway does not have to do anything else. The script language will use the variable in the parent scope at runtime. If the variable does not exist, it is treated like a local variable (see below).
If a variable is defined as
"local"
, Appway checks if there is a default expression. If yes, it is evaluated and the result is used as initial value for the variable. If there is no default expression, the variable's initial value is defined by the type of the variable: 0 for numeric types like Integer or Double, empty collections for Indexed and Named collections, null for all other types like String, Date, User, Person etc.
At the end of this step, the scope for the included screen is ready. Every local and assigned variable of the screen has an initial value, and Appway knows that it can find the values of inherited variables in a higher scope.
Once the included screen has been rendered and the HTML code has been returned to the main screen, the scope for the included screen is discarded by default. Again, this is similar to a function call. The function returns a value at the end (HTML code). Once this is done, there is no way to access the local variables or parameters of the function anymore. The values of these variables are lost when the frame is removed from the stack. The same is true for local and assigned variables of included screens. They live only for as long as the included screen is rendered.
But things get even more complex when we look at the other screen phases "update", "validate" and "process", which are executed after the page has been sent back to the server, e.g. because the user has clicked on the "Next" button. In every of these phases, Appway again has to process the components in the main screen. If it detects an Include component, it generates and initializes a new scope for the included screen, processes the components within this screen, and then discards the scope again.
Note that this is a fundamental difference to how the scope for the main screen is managed. If a process token gets to a screen task, the scope for the referenced screen is generated and initialized when the screen is rendered the first time. But at the end of this render phase, the scope is not discarded. Instead, it lives for as long as the process token stays on this screen task. The effect of this is that you can change the value of a variable in the main screen and it keeps its value for as long as the token is on that screen. This is usually the expected behavior.
Let's make an example. Your main screen has a local variable $counter of type Integer. If this screen is rendered the first time, a new scope is generated and the variable $counter gets an initial value of 0 (the default value for variables of type Integer). The screen contains a text label where the current value of the variable is displayed and a button with a script action with the following script code: "$counter := $counter + 1". If the page is rendered the first time, you see the value "0". If you click on the button, the form is submitted to the server. On the server-side, the attached script action is executed in the process phase and the value of the variable $counter is incremented by one. The screen is rendered again and now displays the update value "1". Whenever you click on the button, the variable's value is incremented by 1. This works only because Appway keeps the scope and all variable values for the main screen for as long as the token stays on the same screen task. We say that this scope is a "persistent scope".
What would happen, if the screen above would be used as include within an other screen? The big difference is that the scope for a screen used as include or template is not persistent. It is generated, initialized and discarded in every screen phase: render, update, validate and process. Due to the fact that the variables in the scope are always initialized with the same initial value, the page would always display the value "0". Sure, the value is incremented by 1 in the process phase, but at the end of this phase, the scope is discarded. If the included screen is rendered later again, a new scope is generated and initialized, and the variable $counter is initialized to 0 again.
The result of this behavior is that local and assigned variables are pretty useless in an included screen, if you expect them to save a modified value for a longer time. They only keep their value for as long as Appway is working in the included screen during the render, update, validate or process phase. Note that inherited variables are usually not affected, because their values are stored in a higher scope (unless the higher scope belongs to another included screen).
People have been fighting this "problem" since we have introduced includes and templates. In order to work around the issue, they had to define the variables in the main screen or process and then inherit them in the include or template. Or they had to work with complex data objects passed to assigned variables of the included screen. So we came up with a solution where you can tell a screen to "remember" its variable values if it is used as include or template.
If this option is enabled, Appway no longer discards the scope of the included screen. Instead, the scope is made persistent and reused in later render, update, validate and process phases. The scope lives for as long as the scope of the main screen lives. If the process token leaves the screen task, the scope of the main screen and all "remembered" scopes of all includes and templates within this main screen are discarded. This also includes "remembered" scopes if included screens within other included screens, or screens included in a template screen etc.
So variables of a screen with this flag get initialized only once and then keep their value. This has the advantage that you now may use local and assigned variables in your include or template and modify their values. But it also comes with a disadvantage: every persistent scope requires some extra space in memory and some extra space when the process data has to be saved to disk.
Let's make a final example where the usage of the "Remember Variables" flag is appropriate:
You want your website visitors to be able to subscribe to an email newsletter. You need this subscription feature all over your website. So you decide to implement it in a screen you then can include in various other screens. The screen contains a single text field where the user can enter an email address. The text field is bound to a local variable $email of type String defined in the screen itself. There is also a "Subscribe" button with an attached script action where the value of the variable $email is written into a database.
Without the "Remember Variables" option, the solution would not work as expected. Although the email address entered by the user is stored in the variable $email in the update phase, this value is lost when the screen's scope is discarded at the end of the update phase. If the script action is then executed during the process phase, a new scope is used and the variable $email has its default value again (which is probably null).
One solution for this problem would be to define the variable $email in every screen where you want to include the newsletter subscription include screen, and then define the variable inside the included screen as "inherited". Another solution would be to use a lot of additional script code to "export" the value of the variable $email at the end of the update phase (maybe store it in the session) and "import" it again at the beginning of the process phase. But both solutions are not very user-friendly and are hard to understand and maintain for other people in your team.
The best solution would be to enable the "Remember Variables" option on the included screen. From now on, the value of the variable $email is remembered between the different screen processing phases.
A final note about the technical implementation:
If the same screen is included multiple times within the same main screen (or nested in different other included screens), every "occurrence" of the included screen gets an independent persistent scope with remembered variables. It is not the case that the includes would share the same remembered scope. The scope is referenced by a unique id which is generated based on the process token id, the component path (the "coordinates" of the Include or Template component within a screen component tree) and the id of the included screen. If the same screen is included multiple times in the same parent screen, at least the component path is different. If the included screen is determined at runtime using an expression, the screen id is different. And if the same screen in included in different main screens on parallel branches inside the same process, the process token id is different. In any case it is guaranteed that every occurrence of an included screen gets its own "remembered variables".
There have been some bug related to scope management for includes and templates which have been fixed in recent versions of Appway. I therefore highly suggest to upgrade to Appway 5.2.3.9 or Appway 5.3.1.
- Stephan
Please
sign in
to add a reply
About this site
|
Terms of use
|
Privacy statement
|
Contact us
© 2025 Appway AG. All Rights Reserved.