Thursday, April 05, 2007

SnTT: Programmable Tabbed Table Reset

I ran across two different applications yesterday that used programmable tabbed tables. One was a table in which the user could choose the tab and one did not display the tabs but allowed the user to pick between them with links. Both violated one of my cardinal interface rules in that you should avoid disorienting the user when presenting information to them. In both of these applications, the state of the tabbed table was retained when the document was saved. That is, if I was on the third tab of the table when I clicked the save button, the next time I opened the document, the tabbed table would still be on the third tab. Now, this could be perfectly good functionality in certain applications. Often it is great to take the user back to the exact place they were when they left off. This provides them with a mental reminder of what is was they were working on. In the case of the two applications in question, however, this was not desired functionality, especially since Notes provides no built-in mechanism for retaining the state information for a given user. In these applications, it makes more sense for the tabbed tables to display the first tab when a document is opened, since this tab contains the key metrics for the document. You see the problem here, right? If Joe opens the Account document and leaves off on tab 5, when I open the doc that is the information I will see. Since I'm not expecting this, there is a momentary feeling of being lost. Even though it is short-lived and I am able to quickly recover from the problem, leaving the user with an unsettling feeling, no matter how brief, does not engender a good user experience.

One of these applications, I'm embarrassed to say, was one of mine. This was merely a sin of omission on my part, since I have addressed this issue in many applications in the past, but I still felt a bit sheepish when I encountered it. Fortunately, the fix is very simple and is a good practice to get into if you are creating programmatic tabbed tables. Here's the scoop...

As you recall, you can make a programmable tabbed table by selecting the proper settings in the table properties dialog box.

To select a particular row in the tabbed table, you use the $table-name field and set it's value to the appropriate row. The $table-name field is created for you when you name the table and the row value is obtained from the row tag name. Both of these values are defined on the Table Programming tab.

You can see in the picture above that I've called the first tab "Tab1" and subsequent tabs are named in a similar fashion. Thus, at it's most basic, the formula to switch from this tab to the fourth tab in this table would be

@SetField("$NavTable" ; "Tab4");

This is a great feature, since it works in both read and edit mode. A programmable tabbed table has many uses. One example is displaying conditional information. I have an application in which usually only certain tabs should be shown, based on user input. By using a programmable tabbed table along with an outline, I provide a nice method to navigate among the various tabs, skipping over those that are not necessary. You can see an example screen below.

If you look at the document properties for a document with a programmable tabbed table, you'll actually see the $table-name field included with all of the other document fields.

Here's where the (potential) problem occurs. When a user edits the document, the current value of $NavTable is saved. So if I save and close when I'm on Tab4, that's the tab the next user will see when they open the document.

In order to avoid this problem, I simply use the code above in the query save event to set this field back to the first tab. Alternatively, you could reset the value when the document is opening. I needed to do this once when I was retrofitting some functionality into an existing application. Rather than mess with the QuerySave event (which had a huge mess of ugly LotusScript), I simply created a CFD field on the form called "SetTabbedTable". The formula for this field was:

@SetField("$FinancialsTable"; "Tab0");

This insured that the user was always presented with the first tab, whether in read mode or edit mode.

Well...that was a really simple tip and I probably provided way more background than you needed, but better to be thorough I say. In any event, this is an easy fix to apply and although it seems rather trivial, remember that the small things add up when we're on the way to user experience nirvana.


Nathan T. Freeman said...

Ho hum... once again, genius is so passe.


4 Jack & Cokes, eh? Sounds like me at Lotusphere on the night after our presentation. hehe

Something I didn't know was that the @SetField would work in read mode. I knew about the RefreshHideFormulas technique, but I wasn't clear that you could do the $field set. Does that only work if you DON'T actually put a field on the form?

Also, does that work from Lotuscript?

Chris Blatnick said...

Genius? Puh-leeze...Look in the mirror mister 73 characters. Now that's genius! :-D

Yes, @SetField in this instance does work in read mode, but (as you point out) you can't have an actual field of that name on the form.

I thought I did do this in LotusScript at one time but I couldn't find it. Someone out there must know.

Happy Easter!

Suchitra said...

hmmm nice.
Why this @If(@IsDocBeingLoaded;
@SetField("$FinancialsTable"; "Tab0");
"") only works when put into a field value and not with computed text.
It should execute in case of computed text i suppose.

dogu said...

Pretty snazzy stuff. Gotta tell ya, the value of this blog is that you provide some incredibly interesting concepts for how to think about putting an app together and then you show us the trick. Breaking out of 'forms, views, agents' mode has been a difficult process (locked in R4.6 for-freaking-ever) but very much fun.
I have a new app I'm working on now that might benefit from this concept. I'm currently using a captioned table but the form is kind of busy. By using this technique, the table goes to one row and, like a caption table, the user clicks one thing to open up the row of interest. Sweet!


Doug Finner

just got another 9" of snow with a nor'easter on the way, you sure you don't want to move to New England???

FWIW, the position that has been approved is looking like a junior developer. No clue what the salary range is but I'm betting is probably a tad less than your current pay. If you happen to know of a good new developer who's looking for a change of scenery, send 'em my way (

dogu said...

I'm trying to decipher your 'drunk hits a deer' graphic. Tell me if I got even close to what I think I'm seeing.

It's a form.
Close/print friendly stuff is actions.
Main table is 2 rows, 2 cols. Row 1 cols 1 & 2 are just static graphics.
Row 2 col 1 is an outline
Row 2 col 2 is the programmed table.
Line one serves as a header and has static text and 'links' that do the @SetField("$NavTable";"RowPrev") thing.
Line two is the content you want displayed - maybe text in the doc, maybe an embedded view, maybe something else.

If I'm not even close, I'm not sure I want you to give me the details, but a hint would be helpful.



Chris Blatnick said...

@Doug: Hint...I'm using an embedded outline and prgrammable table together. You're pretty much on with your description.

Chris Blatnick said...

@Suchitra...Yes, I think it probably would work with computed text too...I'll try it out and let you know if it works.

dogu said...


WOOT! Always nice to know you've actually figured out how something works.

I've also decide I need to stop coming to this blog. Every time you post something, my project list gets's now up to 'every app I have in production and every one I'm developing now'. Let's see, if I work real hard, I should be able to get caught up by...add 6, carry the 3, divide by 24, square it, hmmm hmmm hmmmm, and that computes out to 'never'.

Thank you so VERY much!


Well, off to see what other trouble I can get into.


Chris Blatnick said...

@Suchitra...Nope...surprisingly enough using computed text does NOT work. I thought it might, but I tried it a couple of different ways and couldn't get it to trigger the change. Putting the CFD field back worked flawlessly every time.

Jan Van Puyvelde said...

I must be missing something, because if the $tablename field were computed for display, it would not be saved in the first place.

Chris Blatnick said...

@Jan...You don't actually put a $tablename field on your form. This is actually a sure way to mess yourself up. It's an internal field created automatically by Notes. The CFD field I'm refering to is just a bogus field used for the purpose of resetting the value of $tablename. It's a bit confusing until you play around with it a bit. Feel free to drop me a line if you have any problems or questions. Cheers!

Jan Van Puyvelde said...

@Chris: I don't quite agree: every time I have used programmable tables, it was by adding a $tablename field to the form. That is not "a sure way to mess ... up"; it is included in Designer Help: "you can use a field on the form to control the table. You can use a choice list field that refreshes on change or use a computed field." I have used both these methods a few years ago.
Therefore, it can be assumed that a computed for display field (=my original comment) will work just as well as a computed field (=Designer help).
I do agree that YOUR CFD field contains code to set the value of the $tablename field. But I think that the $tablename field could also be CFD, which would stop it from getting saved (=the point of this blog post).

Chris Blatnick said...

@Jan...Thanks...that is a good thing to know! In the past when I tried to use a field on the form, I encountered problems and to be honest I never tried it again. I remember at some point someone confirming to me that putting your own $tablename field on the form caused problems, so I just carried on with my current technique.

You're sounds like it should work. I'll have to try it though, since with with Notes I don't trust anything! :-D (see my comments to Suchitra in this post...haha). Or have you already done this? If so, your idea is probably the best technique.

Thanks for keeping me honest!

Elf said...

I've done something similar in various survey applications where you have Next and Back buttons.

adibabu kancharla said...

Is there any way to focus on first entry in the embedded outline which used as navigation control for a programmatic tabbed table, when document got opened?

Chris Blatnick said...

@Adibabu can set focus to the first entry in the embedded outline using code similar to that for the tab table. Given an element called "EmbeddedOutline", you can simply use:

FIELD $EmbeddedOutline := $EmbeddedOutline;

@SetField("$SectionEmbedOutline"; 1)

Where the second value is the position of the entry in the outline that you want to hi lite.