Here’s an interesting interface challenge we recently faced: A client needed to place text fields on a layout and fluidly choose which fields would be editable or read-only—the same field might exist in both editable and read-only state on the same layout.
Now, here’s the challenging bit: Each read-only field must have all the same capabilities of its editable cousins—users must be able to scroll, select, and copy text, and the field control must display all rich text formatting entered.
We added one last requirement of our own: Our technique must be lightweight, easily extensible, and must not add meaningless fields to our data tables.
We started out with 4 possibilities—all common techniques in the FileMaker world:
- Limiting access using UI field entry controls
- Limiting access using FileMaker Security
- Presentation using Proxy Calculated Fields
- Presentation using Web Viewers
None of these standard techniques met our client’s needs. We had an interesting problem on our hands! In the end we found two solutions that worked. Our path to each of these is described below. But, if you really hate suspense, you can click here to skip directly to our solutions…
Our text fields: Waiting for a technique to make them secure yet friendly.
Exit Stage Left
Putting our heads together, we quickly ruled out two techniques:
- Disabling Field entry: Browse mode (via the Inspector palette) worked too well. It prevented users from interacting with a field at all – no scrolling, selection, or copying its contents.
- Using Filemaker’s native Security layer to make a field read-only also was too coarse an approach. If a field was read-only, users couldn’t edit it elsewhere on that layout.
Calculated Proxy Fields
We considered a widely-used approach: the time-honored technique of using proxy calculated fields for each field to be read-only. For each field to be read-only, you create an unstored calculated text field, and set its calculated value to the desired field. Out of the box, proxy calculation fields are read-only, scrollable, selectable, and they faithfully preserve any text formatting.
So what’s not to love? The problem lies under the hood. This technique solves a UI problem by creating meaningless data fields, cluttering data tables with entities whose only purpose is presentational. This technique might work well at first, but would create clutter and code management issues as a solution grew.
We also considered using a Web Viewer to display the field. We set the Web Viewer’s source to:
"data:text/html," & [ fieldname ]
This gave us a read-only, scrollable, selectable display of our field data, didn’t require any additional data fields, and was bullet-proof against editing. But the Web Viewer couldn’t display rich text formatting, which was a basic client requirement. Close, but no cigarillo.
Web Viewers: Tantalizing. But no formatting…
Beezwax developer Will Baker suggested a simple, elegant script trigger solution: By triggering a simple script that returned false whenever a field’s onObjectKeystroke and onObjectModify events fired, we could prevent any keyboard edits, and allow scrolling, selection, copying, and even format preservation. We liked this technique a lot—it’s elegant, lightweight, requires only 1 trigger script, and would keep our data tables completely clean.
Unfortunately, this technique had an Achilles heel: Users could still edit field data using cut/paste and drag and drop.
A Single Proxy Field
Returning to the idea of proxy calculated fields resulted in a mini brainstorm: We found we could remove most of this technique’s usual clutter by creating a single, repeating presentational calculated field able to present any number of fields. We defined our single proxy field like this:
Choose ( Get ( CalculationRepetitionNumber ) ; "" ; Extend ( [ field_1 ] ) ; Extend ( [ field_2 ] ) ; Extend ( [ field_3 ] ) // and so on… )
This technique would let us keep data tables clean, even as a solution grew. Our read-only field controls could be scrolled, selected, copied, preserve all formatting, and be edit-proof. This could work.
There was just one annoying fly buzzing in our ointment: If users tried to modify the field, a pesky FileMaker warning would pop up every time. The warning message was technically correct; but users would find it unnecessarily jarring and confusing.
The dreaded warning dialog. “Stop slapping my hands!”
Hey! You Got Chocolate in my Peanut Butter!
Our Reese’s Peanut Butter Cup moment came when our two best ideas bumped into each other. We combined the trigger script technique with the single proxy field technique, getting the best of both: No more pesky dialogs if a user typed into a field (the script trigger intercepted attempted changes), and no more sneaky mouse or menu edits (the calculated field prevented these).
This solution is elegant, lean (just 1 trigger script per database, and 1 additional field per table), and robust (it won’t break if field names change). And from a user’s perspective, it “just works”.
Integrated Proxy Field with Triggers: Bullet-proof, pixel perfect.
Web Viewer Redux
As this article was being written, I had an unexpected “aha” moment: Realizing that our discarded Web Viewer had more tricks up its sleeve, I tried wrapping a field in a GetAsCSS() function, defining the Web Viewer’s source like this:
“data:text/html,” & GetAsCSS ( [ fieldname ] )
And just this simply, the Web Viewer technique was transformed from a discard into an ideal solution — arguably the simplest and most elegant we’d found. With no additional scripts, no additional fields, and no script triggers, this technique preserves all formatting, allows full scrolling, selection, copying, and is bulletproof against edits.
Improved Web Viewers: Lean, Elegant, OS-native.
So Who’s the Real Winner?
We’re calling this a tie. Here are the advantages we see for each technique:
Single Presentation Field with Triggers
- Can display non-white backgrounds (Web Viewers always display a white background unless css/html styling is applied separately).
- Complex text will exactly match original field (in Web Viewer, CSS-rendered text may vary slightly from that in native FileMaker controls).
- Control exactly matches other native FileMaker controls (scroll bars match native FileMaker edit box look and feel).
- Simplest. Most lightweight. Least overhead.
- Provides complete separation between data and presentation layers (no additional data or scripting are created).
- Provides an OS-native look. For example, a FileMaker Web Viewer on OS X Lion displays the new hiding scrollbar look and feel.
Both these techniques earn a well-deserved place in our toolbox. Which we choose will likely depend on specific project needs and the preferences of a given developer. Which technique do you like best? Please feel free to comment on which you’d prefer, or if you have a different approach to this problem.
Update: To my chagrin, I realized the demo file was never included with this post. Here it is, long overdue: