Namespacing Layout Variables

77 views
Skip to first unread message

Jeremy Bante

unread,
Apr 13, 2015, 5:41:17 PM4/13/15
to fmsta...@googlegroups.com
In some discussions at Beezwax, we've grown increasingly excited by the technique of using "Hide Object When..." calculations to set variables to be displayed in the layout. (This could already be accomplished with conditional formatting calculations, but Hide Object When is turning out to be more bullet-proof.) Variables set by a layout and variables set by a script can step on each others toes if there are any naming collisions, so namespacing was suggested to deal with it. Any proposals?

Malcolm Fitzgerald

unread,
Apr 13, 2015, 6:42:13 PM4/13/15
to fmsta...@googlegroups.com
> --

Layout Object Variables, abbreviated to lov, with an underscore
separator appended to produce $$lov_.

malcolm

Jeremy Bante

unread,
Apr 13, 2015, 6:46:49 PM4/13/15
to fmsta...@googlegroups.com
I think it's worth pointing out that one of the benefits of layout object variables is that they can be locally scoped $variables, rather than needing to be $$VARIABLES.

Matt Petrowsky

unread,
Apr 13, 2015, 6:54:58 PM4/13/15
to fmsta...@googlegroups.com

The two prefixes I’ve been using myself relate to translation support and then general purpose display variables.

$$UI.LITERALNAME for ui text, where

$$UI.VARIABLES = “Variables”
and
$$UI.PRODUCTS = “Products”

This way when reading in the ui without showing Sample Data, you know what $$UI.THISTEXT is going to hold - “This text”. ;)

When it’s an on-the-fly display variable the prefix is $$DISPLAY.SOMESTRING

$$DISPLAY.ITEMCOUNT = Get ( FoundCount ) & “ “ & Plural ( $$UI.ITEMS ; Get ( FoundCount ) )

Following our conventions… These would just be lowercased.

$ui.items
or
$display.devicename

What do you think?

Matt

--
You received this message because you are subscribed to the Google Groups "FileMaker Development Standards" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fmstandards...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jeremy Bante

unread,
Apr 13, 2015, 6:59:30 PM4/13/15
to fmsta...@googlegroups.com
Sounds reasonable enough. What do you use for variables set by the layout that are not displayed, e.g. variables to log how long it takes for the layout to render?

On Monday, April 13, 2015 at 3:54:58 PM UTC-7, Matt Petrowsky wrote:

$ui.items

or
$display.devicename

Matt Petrowsky

unread,
Apr 13, 2015, 7:02:28 PM4/13/15
to fmsta...@googlegroups.com
I usually prefix any temporary variables, which is what I would consider
layout local variables, with an underscore. I often have a a full Data
Viewer so having them sort to the top is preferable.

$_dev.start
$_dev.end
$_dev.diff

Daniel Smith

unread,
Apr 13, 2015, 7:09:12 PM4/13/15
to filemakerstandards.org
I haven't use this technique that much lately, but the last time I did I used: $layout.variableName

I would think you would prepend it with a tilde (~) if it was for utility purposes like logging layout render time. But that might also depend on what accesses that variable after it's set.

I think Matt's idea to use custom prefixes for common features like translation makes a lot of sense.

To unsubscribe from this group and stop receiving emails from it, send an email to fmstandards+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "FileMaker Development Standards" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fmstandards+unsubscribe@googlegroups.com.

Perren Smith

unread,
Apr 13, 2015, 7:15:30 PM4/13/15
to fmsta...@googlegroups.com
Matt,

In my testing I found these layout local vars to be the exact opposite of temporary. They’ll persist with a window as long as it exists and be inherited by any new windows created when that one is frontmost.

The only way to kill them off is to Null them out explicitly or close the file.

Thanks,

—Perren

Matt Petrowsky

unread,
Apr 13, 2015, 7:30:54 PM4/13/15
to fmsta...@googlegroups.com
My usage of “temporary” relates to when instantiated via Eval of
Conditional Formatting. Thus leaving one layout to head to another means
they could easily be overwritten if you use the same variable name on
another layout. It’s just my mental perception of thinking of them as
temporary, not their literal result. :(

Yes, they may persist, but I consider them temporary and don’t code
based on the assumption that they’ll always be there or be the same -
such as a $$GLOBAL.VAR until explicitly changed.

But, yes, you have to kill them if you are using them on the layout and
you use them on more than one layout. You’ll get unexpected results if
you don’t wipe them.

I’ve used a global var of $$MESSAGE with $display.extra on multiple
layouts.

Thus <<$$UI.NOTICE>>: <<$$MESSAGE>> <<$display.extra>> allowed me to
show additional information to a system message on a per layout basis.
But the $display.extra would obviously persist unless I accounted for
it.

On each layout a conditional formatting eval wipes $display.extra. I
know I could use a OnLayoutExit and set things, but I got addicted to
using the calc engine via Conditional Formatting (probably a bad habit).

I have three of these text blocks stacked on each other. One for Error,
one for Warn, one for Info. Putting icons in them and hacking the CSS to
left align makes for a very good user messaging system. They are
controlled via the Hide calc using variable named $$MESSAGE.SHOW where
0 is Error, 1 is warn and 2 is Info. Blank or lack of $$MESSAGE.SHOW
means no messages shows.

Matt

Malcolm Fitzgerald

unread,
Apr 13, 2015, 10:40:46 PM4/13/15
to fmsta...@googlegroups.com
On 14/04/2015 10:46 am, Jeremy Bante wrote:
I think it's worth pointing out that one of the benefits of layout object variables is that they can be locally scoped $variables, rather than needing to be $$VARIABLES.
wow! What is the local scope? Is it the layout, the record, the table, the window?

malcolm

Perren Smith

unread,
Apr 13, 2015, 10:46:05 PM4/13/15
to fmsta...@googlegroups.com
The design surface (per file). 
--

Mark Scott

unread,
Apr 14, 2015, 1:06:50 AM4/14/15
to fmsta...@googlegroups.com
I’ve been namespacing my global variables with dot nomenclature too; I’m certain I picked that up from you, Matt, via previous fmstds.org discussions.

I like your suggestion to carry that over to local variables when used in this way.

Mark

Mark Scott

unread,
Apr 14, 2015, 1:11:49 AM4/14/15
to fmsta...@googlegroups.com
I like that idea.  These do seem to be of a more “private” nature (“private” used loosely here ;-) compared with a variable intended for display.

Mark Scott

unread,
Apr 14, 2015, 1:19:03 AM4/14/15
to fmsta...@googlegroups.com
I wonder if it makes sense, in cases where there might be a potential variable-name conflict between layouts, to include the layout name in the namespace prefix, e.g., “$ui.layoutname.something”? Just thinking aloud here.

Malcolm Fitzgerald

unread,
Apr 14, 2015, 1:28:10 AM4/14/15
to fmsta...@googlegroups.com
Oh my goodness!

I've just created a calc to define a local variable in one window on a layout based on Appointments. I've placed a merge variable on a different layout based on Contacts, using the local variable as a data source. The second layout happily displays the local variable defined in a different layout. It doesn't update immediately, it needs a reason to refresh the object, but there it is.

Dynamic text labels are so much fun.

I noticed that the merge variable is updated switching mode to Browse or Preview mode but not when switching to Find mode, so that's one limit on it's use.

Malcolm


On 14/04/2015 2:46 pm, Perren Smith wrote:

Mike Duncan

unread,
Apr 14, 2015, 8:38:48 AM4/14/15
to fmsta...@googlegroups.com
I like the idea of putting variables in some kind of name space, but I am not sure about limiting them to where they were defined from or where they intend to be used. That might not always fit in with how they are used.

Are there any downsides to using a dot as delimiter? I have avoided them in all other naming conventions, for various reasons, so I am trying to think of situations where they might break.


Corn Walker

unread,
Apr 15, 2015, 12:15:56 PM4/15/15
to fmsta...@googlegroups.com
On Apr 13, 2015, at 10:40 PM, Malcolm Fitzgerald <mal...@notyourhomework.net> wrote:

> wow! What is the local scope? Is it the layout, the record, the table, the window?

Variables have the following scopes:

$$variable - scope is every layout/window/script in the file for the duration that the file is open.

$variable - scope is every layout/window in the file for the duration of a particular script stack level

variable - scope is the duration of the evaluation of the Let() statement in which they are assigned


The confusing thing about the $variable is that the scope is to a script stack level. When no script is running the script stack level is '0' and any $variable declared at that time (e.g. through Let() statements via Conditional Formatting or other areas providing access to the calculation engine) will persist until they are cleared or the file is closed. HOWEVER if a script is running (e.g. script stack level > 0) you will not have access to those variables during the execution of the script. Each subscript that is run increases the script level. When a script is placed on the stack any $variables declared previously fall out of scope; when that script exits any $variables defined while that script was running are released while $variables declared before come back into scope.

As long as the object defining the variable is on the layout with the variable, this is usually not a problem. However, if you use a merge $variable on a layout that is defined by an object on another layout, and the window is refreshed while a script is running, you may see the value in the merge $variable disappear. Refreshing the window after the script exits will cause the value to reappear.

Cheers,
-corn

Jonathan Fletcher

unread,
Apr 15, 2015, 4:00:31 PM4/15/15
to fmsta...@googlegroups.com
Thanks for that, Corn! That’s the missing piece I needed!
> --
> You received this message because you are subscribed to the Google Groups "FileMaker Development Standards" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to fmstandards...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

--
Jonathan Fletcher
FileMaker Certified Developer (9 thru 13)

Fletcher Data Consulting, LLC
A FileMaker Business Alliance Partner
jona...@fletcherdata.com
http://www.fletcherdata.com
502-509-7137

Kentuckiana's FileMaker Developers Group
Next meeting: Tuesday, April 28th, noon to 3:30
http://www.kyfmp.com

Malcolm Fitzgerald

unread,
Apr 15, 2015, 6:07:47 PM4/15/15
to fmsta...@googlegroups.com
Yes. It is a situation that screams "loophole" doesn't it.

A complicating factor - tripwire #1 - is that the layout display is only
refreshed under certain conditions. Until a refresh occurs the screen
display can be out of synch with the current data. And - tripwire #2 -
only some sections of the screen are refreshed. So it's possible for
different elements on the screen to display different values for the
$variable simultaneously.

In one test I placed a button label and a separate text object with the
same merge text onto the layout. The script attached to the button would
modify a global variable and refresh the window. The global variable was
used in a Choose() function by the Hide Object calc on the button and
text object. This is setting up a situation where the $variable is
intially defined at script stack level 0 and redefined at script stack
level 1. As the mouse was clicked the text object and button labelled
changed as desired. The refresh window script step was needed for the
display to update. But the onhover state is actively tracked. While the
mouse was over the button the display carried the changed value. When
the mouse moved away the screen region defined by the button was
refreshed and the button label now displayed the original value defined
at script stack level 0. However, the text object beside it retained the
value defined at script stack level 1.

Malcolm

Corn Walker

unread,
Apr 15, 2015, 7:09:10 PM4/15/15
to fmsta...@googlegroups.com
I neglected to mention the stacking order (z-order) of layout objects. Layout objects are drawn back to front in z-order so if you have a variable farther back in the z-order than the object that defines them you can end up with a variable whose value is seemingly out of sync.

Cheers,
-corn

Jeremy Bante

unread,
Apr 15, 2015, 7:18:36 PM4/15/15
to fmsta...@googlegroups.com
On Wednesday, April 15, 2015 at 4:09:10 PM UTC-7, corn wrote:
I neglected to mention the stacking order (z-order) of layout objects. Layout objects are drawn back to front in z-order so if you have a variable farther back in the z-order than the object that defines them you can end up with a variable whose value is seemingly out of sync.

The main advantage to using "Hide Object When" calculations instead of conditional formatting is that this is no longer an issue. The object hiding calculations appear to be evaluated for all objects before anything is rendered. An object hiding calculation can even set a variable to be displayed in the same object very reliably. Conditional formatting is still necessary when the same variable must be used to show several different values, such as for each record in a list view or portal, and this is just about the only time I find myself still using conditional formatting to set merge variables.

Matt Petrowsky

unread,
Apr 15, 2015, 7:21:00 PM4/15/15
to fmsta...@googlegroups.com
Does the Hide eval when off the visible portion of the layout?

Matt Petrowsky

unread,
Apr 15, 2015, 7:23:27 PM4/15/15
to fmsta...@googlegroups.com
Yep, it sure does. Nice find!

Matt Petrowsky

unread,
Apr 15, 2015, 7:27:13 PM4/15/15
to fmsta...@googlegroups.com
I think I’m going to dual purpose a text block and name it
“QuickFind & Variables”.

I’ll put the merge fields in the text for tightly controlled QuickFind
fields (because I turn off all other fields with Command-Option-A
deselect QF) and also put variable declarations within the Hide calc.

Reduces my multiple elements down to fewer. :)

Malcolm Fitzgerald

unread,
Apr 15, 2015, 8:12:18 PM4/15/15
to fmsta...@googlegroups.com
On 16/04/2015 11:20 am, Matt Petrowsky wrote:
> Does the Hide eval when off the visible portion of the layout?
>
Yes. And, of course, you could also have the hide calc evaluate to True
so the object is never displayed.

malcolm

Matt Petrowsky

unread,
Apr 15, 2015, 8:40:34 PM4/15/15
to fmsta...@googlegroups.com

Yep. Got it.

In fact. One of my favorite patterns, although it is a hack because it’s somewhat hidden, is to use a single Refresh Object step on a button. The button is a simple Boolean toggle so the calc code of the refresh step is as follows.

Let ( [
    $$TOGGLE = not $$TOGGLE;
    $display.buttontext = If ( $$TOGGLE ; $$UI.ON ; $$UI.OFF )
];
    "button.toggle"
)

The button is aptly named “button.toggle” of course and uses a the merge var of <<$display.buttontext>>.

Using Conditional formatting was sketchy when using a local var so I had to use a trigger script to initialize. This defeated the purpose of trying to toggle a global var without having a script. But using the Hide calc allows me to bypass the script.

Wehawwww!

--

Ben Graham

unread,
Apr 15, 2015, 9:04:13 PM4/15/15
to fmsta...@googlegroups.com
I can see your excited about this Matt.  However I think I am missing something.  What triggers the Refresh Object step? Or can you explain a use case for this. 

Thanks for any clarification. 

Cheers,
Ben

Matt Petrowsky

unread,
Apr 15, 2015, 9:11:40 PM4/15/15
to fmsta...@googlegroups.com
The example code would be within the calculation for a Refresh Object
step assigned to a button - no scripts.

Its only purpose is to toggle a value within a global variable. It
avoids having to create a script for this and tightly couples the logic
to the button object itself. If the button uses Conditional Formatting
for say, green means “on” and red means “off” then the Refresh
Object - targeting itself - addresses two things. 1) It toggles the
global var and 2) refreshes the Conditional Formatting of the button.

I was using global variables for the text of the button, however, using
local variables - as we’ve been discussing - keeps your number of
global variables lower and is only used on an as-needed basis.

Initializing a local variable via the Hide calc preempts any other
layout evaluations - such as Conditional Formatting. That’s what
Jeremy was pointing out.

Does this help out?

Matt
>> <https://groups.google.com/d/optout>.
>>
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "FileMaker Development Standards" group.
>> To unsubscribe from this group and stop receiving emails from it,
>> send an email to fmstandards...@googlegroups.com
>> <mailto:fmstandards...@googlegroups.com>.
>> For more options, visit https://groups.google.com/d/optout
>> <https://groups.google.com/d/optout>.

Ben Graham

unread,
Apr 15, 2015, 9:20:40 PM4/15/15
to fmsta...@googlegroups.com
Yes it helps, only, the Refresh Object step is a single step on the button itself then and is triggered when the layout is refreshed or the button is pressed, meaning both?

Matt Petrowsky

unread,
Apr 15, 2015, 9:24:51 PM4/15/15
to fmsta...@googlegroups.com

The order of operations are as follows.

  • User clicks button
  • Calc in Refresh step evals
  • Globa var is toggled
  • Conditional formatting is eval’d (I think)
  • Button object itself is refreshed based on cond formatting

The Refresh Object step does not have anything to do with the Refresh Window step - other than sharing the word “Refresh”. It was added to FMP because Refresh Window can be very costly - especially on FM Go.

Matt

--
You received this message because you are subscribed to the Google Groups "FileMaker Development Standards" group.

--
You received this message because you are subscribed to the Google Groups "FileMaker Development Standards" group.

To unsubscribe from this group and stop receiving emails from it, send an email to fmstandards...@googlegroups.com fmstandards...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "FileMaker Development Standards" group.

To unsubscribe from this group and stop receiving emails from it, send an email to fmstandards...@googlegroups.com fmstandards...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout https://groups.google.com/d/optout.

Ben Graham

unread,
Apr 15, 2015, 9:45:24 PM4/15/15
to fmsta...@googlegroups.com
Thanks. Yes it is really nice compared to the added $$GLOBLE.VARIABLES :)
Reply all
Reply to author
Forward
0 new messages