Your Development & Design Resource

Context-Sensitive Tabbed Navigation in the Lotus Notes Client

Revolution CRM - Context Sensitive Tab Navigation ExampleIt's something that gave our CRM product (Revolution CRM) an amazingly fresh and simple-to-navigate Notes-client user interface, and despite it's seemingly simple function... implementing a context-sensitive navigation system for a table-based form layout in the Lotus Notes client required quite a bit of hackery. In this article, I'll showcase exactly what we did to facilitate such functionality and ultimately provide our users with a simple, intuitive interface (at least in my and several of our users' opinions)

We start off by creating a Programmed Table, turning off the table tabs to the UI (fig. 1), then naming the table row and assigning each row tag a unique name (fig. 2).

(fig. 1) - Table Properties

(fig. 2) - Disabling Tabs Table Properties

Now that we have our Programmed Table, we need to create the dynamic display functionality. To do this, we simply create a field called $row:

Field Name: $row
Field Type: Text - Computed for Display (CFD)
Field Formula:@If($row="" ; "1"; $row)

And now that we have our Programmed Table and programatic control field, we'll work on the tabbed interface.

You can make this navigation system look however you would like, but the ultimate goal is to have an active and inactive state for each of your navigation tabs, and set the active table row's correlating navigation tab to it's "active" state. To do this, we'll first build out the navigator. And for this navigator, we'll use a table, and more specifically, a table cell.

We are going to put a hotspot in a table cell, and when said hotspot is clicked, I want to 1) set the current navigation tab to it's "active" state and 2) activate the correlating Programatic Table row. For 1, we'll need to place the following formula in the cell properties of the navigation tab (fig. 3):

(fig. 3) - Computed Cell Properties


The above code, checks to see if the first tab is active, and if so, sets the cell background-image to "activetab.gif". Otherwise, it remains "tab.gif", which is the application's inactive tab background-image. Pretty simple approach, so far. The problem that we ran into is that we could not successfully "reload" the page to display the now-active navigation tab nor the now-active Programmed Table row.

Bring on the hackery!

We start by using Lotuscript on the form at various form events, and then an on-click function loaded from a script libary. We'll start by displaying a list of form events and their script counterparts:


Sub Queryopen(Source As Notesuidocument, Mode As Integer, Isnewdoc As Variant, Continue As Variant)

    Set w = New NotesUIWorkspace
    Set s = New NotesSession
    Set db = s.CurrentDatabase
    Set uidoc = source

    Call InitializeRow ( s, uidoc )

End Sub


Sub Queryclose(Source As Notesuidocument, Continue As Variant)

    Call FinalizeRow ( s, source )

End Sub


Sub Postopen(Source As Notesuidocument)

    Set doc = source.Document

End Sub


Dim s As NotesSession
Dim w As NotesUIWorkspace
Dim db As NotesDatabase
Dim doc As NotesDocument
Dim uidoc As notesuidocument

And now, for our on-click function. On each "tab", you'll want to create a hotspot with the following Lotuscript (replacing the "1" with the intended Programmed Table's Row name:

Sub Click(Source As Button)

    Call OnClickTab ( w, s, uidoc, doc, "1" )

End Sub

And now, for our OnClickTab, InitializeRow, and FinalizeRow functions:

Sub OnClickTab ( w As NotesUIWorkspace, s As NotesSession, uidoc As NotesUIDocument, doc As NotesDocument, row As String )
' FUNCTION: OnClickTab ( w, s, uidoc, doc, row )
' PURPOSE: Change the row the the programmable table
'      w ( NotesUIWorkspace ) - global ui workspace
'      s ( NotesSession ) - global session
'      uidoc ( NotesUIDocument ) - notes ui document
'      doc ( NotesDocument ) - notes backend document
'      row ( row ) - row to set

  If uidoc.editmode Then
    Call doc.ReplaceItemValue("$row", row)
    Call uidoc.refresh
    Call s.setEnvironmentVar("RevolutionRow", row)
    Call uidoc.close
    Call w.EditDocument(False , uidoc.Document)
  End If

End Sub

Sub InitializeRow ( s As Notessession, uidoc As notesuidocument )
' FUNCTION: InitializeRow ( uidoc )
' PURPOSE: Initialize the row to one pressed by user
'      s ( NotesSession ) - global session
'      uidoc ( NotesUIDocument ) - current ui document

  Dim doc As NotesDocument
  Dim row As String

  Set doc = uidoc.Document

  If doc Is Nothing Then Exit Sub

    If uidoc.editmode Then
      Call doc.ReplaceItemValue("$row" , "1")
      row = s.getEnvironmentString("RevolutionRow")
        If row = "" Then row = "1"
          Call doc.ReplaceItemValue("$row", row)
      End If
End Sub

Sub FinalizeRow ( s As NotesSession, uidoc As notesuidocument )

' FUNCTION: FinalizeRow ( s, uidoc )
' PURPOSE: Reset the rows to first row
'      s ( NotesSession ) - global session
'      uidoc ( NotesUIDocument ) - current ui document

  Call s.setEnvironmentVar("RevolutionRow", "1")
End Sub

Now this is a simple example of how you can manually refresh the current UI to not only display the currently active Programmed Table row, but also the currently active Navigation tab. You could just as well conditionally set font colors, weight, and even the text itself by simply computing the values based on the $row field - thus completely allowing your applications to provide a more controlled and more intuitive UI for your users.

Technorati tags:

About the author: Chris Toohey

Thought Leadership, Web & Mobile Application Development, Solutions Integration, Technical Writing & Mentoring

A published developer and webmaster of, Chris Toohey specializes in platform application development, solutions integration, and evangelism of platform capabilities and best practices.

More from is powered by IBM Notes Domino XPages & hosted by Prominic.NET

Contact Us

Use our Contact / Feedback form or one of these email addresses:

Creative Commons License

Except where otherwise noted, by Chris Toohey is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.