Difference between revisions of "OnChange"
(inputs and outputs) |
|||
(5 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
[[Category:Attributes]] | [[Category:Attributes]] | ||
− | + | ||
+ | __TOC__ | ||
+ | {{ReleaseBar}} | ||
The [[OnChange]] attribute of a variable contains an [[Expression Syntax|expression]] that gets evaluated when the [[Definition]] of a variable changes. | The [[OnChange]] attribute of a variable contains an [[Expression Syntax|expression]] that gets evaluated when the [[Definition]] of a variable changes. | ||
− | When a variable is defined as a [[Choice]] or [[Checkbox]], the expression is evaluated when the user changes the selection. For a [[Table]], the expression is not evaluated when individual cells are edited, but it is evaluated when the final edit is made (e.g., when the green checkbox is pressed or | + | When a variable is defined as a [[Choice]] or [[Checkbox]], the expression is evaluated when the user changes the selection. For a [[Table]], the expression is not evaluated when individual cells are edited, but it is evaluated when the final edit is made (e.g., when the green checkbox is pressed or Edit table window is closed). |
The expression can contain side-effects. For example, within the expression, you can assign to a global variable using the := operator. Such side-effects are not permitted in variable definitions. The result of the evaluation is not saved and is never used. Hence, the whole purpose of the expression is to enact some sort of side-effect. | The expression can contain side-effects. For example, within the expression, you can assign to a global variable using the := operator. Such side-effects are not permitted in variable definitions. The result of the evaluation is not saved and is never used. Hence, the whole purpose of the expression is to enact some sort of side-effect. | ||
The expression syntax is the same as the syntax for a [[Definition]] attribute. | The expression syntax is the same as the syntax for a [[Definition]] attribute. | ||
− | |||
− | |||
The [[OnChange]] expression is always evaluated in [[Evaluation Modes|mid-mode]]. | The [[OnChange]] expression is always evaluated in [[Evaluation Modes|mid-mode]]. | ||
− | Before you can access the [[OnChange]] attribute for a variable in the [[Attribute | + | Before you can access the [[OnChange]] attribute for a variable in the [[Attribute panel]] or [[Object Window]], you need to turn on the attribute visibility from the [[Manage_attributes#Attributes_dialog|Attributes Dialog]] on the '''Object''' menu. |
− | = Assignment = | + | == Assignment == |
+ | When you change the [[Definition]] of a variable using the [[Assignment_Operator::_::%3D|Assignment Operator, :=]], the [[OnChange]] expression for that variable evaluates, unless it is already running. The fact that it doesn't run a second time if already running enables some interesting capabilities. | ||
− | + | An [[OnChange]] attribute can change its own [[Definition]]. As an example, suppose that a variable <code>X</code> has the following as its [[OnChange]] expression: | |
+ | :<code>X := "" & (Definition of X)</code> | ||
− | |||
− | |||
When a user enters a value, it is always converted to text. When the value is first changed, [[OnChange]] runs. It in turn alters the value again, but [[OnChange]] is not launched a second time because it is already running. | When a user enters a value, it is always converted to text. When the value is first changed, [[OnChange]] runs. It in turn alters the value again, but [[OnChange]] is not launched a second time because it is already running. | ||
Two or more input variables can change each other via their [[OnChange]] attributes to keep them mutually consistent. For example, suppose you have two inputs variables, <code>GMT_Time</code> and <code>Local_Time</code>, and you have a variable named <code>Time_Offset</code> that relates the two. You set | Two or more input variables can change each other via their [[OnChange]] attributes to keep them mutually consistent. For example, suppose you have two inputs variables, <code>GMT_Time</code> and <code>Local_Time</code>, and you have a variable named <code>Time_Offset</code> that relates the two. You set | ||
− | + | :<code>OnChange GMT_Time : Local_Time := GMT_Time + Time_Offset</code> | |
− | + | :<code>OnChange Local_Time : GMT_Time := Local_Time - Time_Offset</code> | |
− | Now a user enters a time into the GMT_Time input. Local_time immediately adjusts. Or he enters a time into the Local_time input -- GMT_Time immediately adjusts. In the first case, <code>OnChange of GMT_Time</code> evaluates, which changes the definition of Local_time, which in turn triggers <code>OnChange of Local_Time</code>. Local_time actually changes the definition of GMT_Time again, but to the same value it already has, but <code>OnClick of GMT_Time</code> does not run again because it is already active; hence, the loop terminates. | + | |
+ | Now a user enters a time into the <code>GMT_Time input</code>. <code>Local_time</code> immediately adjusts. Or he enters a time into the <code>Local_time</code> input -- GMT_Time immediately adjusts. In the first case, <code>OnChange of GMT_Time</code> evaluates, which changes the definition of <code>Local_time</code>, which in turn triggers <code>OnChange of Local_Time</code>. Local_time actually changes the definition of <code>GMT_Time</code> again, but to the same value it already has, but <code>OnClick of GMT_Time</code> does not run again because it is already active; hence, the loop terminates. | ||
+ | |||
+ | == Inputs and Outputs == | ||
+ | If the [[OnChange]] attribute of <code>X</code> uses the value of <code>Y</code>, then <code>Y</code> will show up on the list of '''Inputs''' for <code>X</code> in the [[Object Window]], and <code>X</code> will be in the list of '''Outputs''' for <code>Y</code>. If <code>Z</code> is assigned to in the [[OnChange]] attribute of <code>X</code>, then <code>Z</code> will appear as an '''Output''' of <code>X</code> and <code>X</code> will appear as an '''Input''' of <code>Z</code>. However, on the diagram, arrows are not show to depict these dependencies. | ||
+ | |||
+ | {{Release|1=6.6|2=|3= | ||
+ | == Event that triggered the change == | ||
+ | (''New in [[Analytica 6.6]]'') | ||
+ | |||
+ | There are three local variables that provide some information about what event triggered the change to the definition (which in turn triggered the evaluation of your [[OnChange]] expression). | ||
+ | ; <code>_trigger_event</code> | ||
+ | :: The type of event that changed the Definition. Possible values are: | ||
+ | :::<code>"Enter"</code>: The enter key was pressed to finish an edit. | ||
+ | :::<code>"Tab"</code>: User pressed tab key to leave the field, causing the definition to enter. | ||
+ | :::<code>"LostFocus"</code>: user clicked out of the definition field or did something that relinquished the UI focus on the definition field. | ||
+ | :::<code>"Assignment"</code>: An assignment operation in a different expression changed the value. (The expression with the assignment is revealed by <code>_trigger_from_obj</code> and <code>_trigger_from_att</code>). | ||
+ | :::<code>"Other"</code>: Catch all for other event categories. | ||
+ | :::<code>"None"</code>: The value is not set. | ||
+ | ; <code>_trigger_from_obj</code> | ||
+ | :: A [[handle]] to the object that triggered the change. If the user was editing in a user input (a FormNode), this is a handle to the input node (in which case, <code>Original Of (_trigger_from_obj)</code> is probably a handle to Self. For an <code>"Assignment"</code> event, this is the object with the assignment expression. | ||
+ | ; <code>_trigger_from_att</code> | ||
+ | :: A [[handle]] to the attribute that triggered the change. Usually <code>Definition</code> for cases where a user entered the value. Or it is the attribute that contained the <code>"Assignment"</code> expression. | ||
+ | |||
+ | One useful case is where you want to "press a button" when the user changes a user input control of text box value, but you don't want to automatically press the button if the user leaves by clicking out of the text box (such as by pressing the button himself). You don't want it to fire in the second case because that would press the button twice. To accomplish this, you can use: | ||
+ | |||
+ | :[[OnChange]]: <code>[[If]] _trigger_event = "Enter" [[Then]] My_Submit_Button</code> | ||
+ | |||
+ | One caveat is that if your submit button might change the value again, perhaps by clearing the text after processing, the infinite loop protection described above in <code>[[#Assignment]]</code> will prevent the change from taking place. You can overcome that using: | ||
+ | |||
+ | :[[OnChange]]: <code>[[If]] _trigger_event = "Enter" [[Then]] [[EvaluateScript]](Identifier of My_Submit_Button, queueIt:True)</code> | ||
+ | |||
+ | which queues the button press as if it were a separate UI event. | ||
+ | |||
+ | The UI event types ("Enter", "Tab", "LostFocus") are only available in desktop Analytica, and aren't used in [[ADE]] or [[ACP]]. | ||
+ | }} | ||
− | |||
− | + | == History == | |
+ | The [[OnChange]] attribute was introduced in [[Analytica 4.6]]. It replaces the [[Script]] attribute when used for [[Choice]] and [[Checkbox]] controls prior to [[Analytica 4.6]]. You can use [[OnChange]] for any variable, including text inputs, where [[Script]] was only available for user input variables using [[Checkbox]] or [[Choice]] functions. [[OnChange]] expects an [[Expression_Syntax|expression]] using the standard Analytica syntax, where the [[Script]] attribute expects [[Typescript]], which meant you had to learn a slightly different syntax to use it. The [[Script]] attribute still works in 4.6 so that legacy models still work. If a variable contains both [[OnChange]] and [[Script]], it evaluates [[OnChange]] before [[Script]]. | ||
− | + | Local variables <code>_trigger_event</code>, <code>_trigger_from_obj</code> and <code>_trigger_from_att</code> were added in [[Analytica 6.6]]. | |
+ | == See Also == | ||
+ | * [[Onchange attribute]] | ||
* [[Choice]] | * [[Choice]] | ||
* [[Checkbox]] | * [[Checkbox]] | ||
* [[OnClick]] | * [[OnClick]] | ||
+ | * [[Creating Interfaces for End Users]] |
Latest revision as of 21:37, 31 May 2025
Release: | • |
---|
The OnChange attribute of a variable contains an expression that gets evaluated when the Definition of a variable changes.
When a variable is defined as a Choice or Checkbox, the expression is evaluated when the user changes the selection. For a Table, the expression is not evaluated when individual cells are edited, but it is evaluated when the final edit is made (e.g., when the green checkbox is pressed or Edit table window is closed).
The expression can contain side-effects. For example, within the expression, you can assign to a global variable using the := operator. Such side-effects are not permitted in variable definitions. The result of the evaluation is not saved and is never used. Hence, the whole purpose of the expression is to enact some sort of side-effect.
The expression syntax is the same as the syntax for a Definition attribute.
The OnChange expression is always evaluated in mid-mode.
Before you can access the OnChange attribute for a variable in the Attribute panel or Object Window, you need to turn on the attribute visibility from the Attributes Dialog on the Object menu.
Assignment
When you change the Definition of a variable using the Assignment Operator, :=, the OnChange expression for that variable evaluates, unless it is already running. The fact that it doesn't run a second time if already running enables some interesting capabilities.
An OnChange attribute can change its own Definition. As an example, suppose that a variable X
has the following as its OnChange expression:
X := "" & (Definition of X)
When a user enters a value, it is always converted to text. When the value is first changed, OnChange runs. It in turn alters the value again, but OnChange is not launched a second time because it is already running.
Two or more input variables can change each other via their OnChange attributes to keep them mutually consistent. For example, suppose you have two inputs variables, GMT_Time
and Local_Time
, and you have a variable named Time_Offset
that relates the two. You set
OnChange GMT_Time : Local_Time := GMT_Time + Time_Offset
OnChange Local_Time : GMT_Time := Local_Time - Time_Offset
Now a user enters a time into the GMT_Time input
. Local_time
immediately adjusts. Or he enters a time into the Local_time
input -- GMT_Time immediately adjusts. In the first case, OnChange of GMT_Time
evaluates, which changes the definition of Local_time
, which in turn triggers OnChange of Local_Time
. Local_time actually changes the definition of GMT_Time
again, but to the same value it already has, but OnClick of GMT_Time
does not run again because it is already active; hence, the loop terminates.
Inputs and Outputs
If the OnChange attribute of X
uses the value of Y
, then Y
will show up on the list of Inputs for X
in the Object Window, and X
will be in the list of Outputs for Y
. If Z
is assigned to in the OnChange attribute of X
, then Z
will appear as an Output of X
and X
will appear as an Input of Z
. However, on the diagram, arrows are not show to depict these dependencies.
History
The OnChange attribute was introduced in Analytica 4.6. It replaces the Script attribute when used for Choice and Checkbox controls prior to Analytica 4.6. You can use OnChange for any variable, including text inputs, where Script was only available for user input variables using Checkbox or Choice functions. OnChange expects an expression using the standard Analytica syntax, where the Script attribute expects Typescript, which meant you had to learn a slightly different syntax to use it. The Script attribute still works in 4.6 so that legacy models still work. If a variable contains both OnChange and Script, it evaluates OnChange before Script.
Local variables _trigger_event
, _trigger_from_obj
and _trigger_from_att
were added in Analytica 6.6.
Enable comment auto-refresher