Rick Strahl's Weblog
Rick Strahl's FoxPro and Web Connection Weblog
White Papers | Products | Message Board | News |

Handling BindingErrors in Tab Pages


July 15, 2008 •

West Wind Web Connection 5.37 introduced a new JavaScript 'hook' function that allows you trap binding error clicks in a page. When using ControlSource binding any binding errors can be  displayed in the page and the messages include links to the controls in question. For simple pages and controls this looks something like this:

 ErrorDisplay

When you click on any of the links on the error list the field is highlighted and the cursor moved there so you can immediately start editing the entry and fix whatever the problem is.

However, when working with Tab pages things are a bit different. The issue is that you may end up having errors on multiple pages of a wwWebTabControl and some of these controls maybe on pages that are not currently visible. For example, check out this page from the sample if you submitted the page on any page other than the PostBacks page:

TabCapture

If you were to click on the Name cannot be empty link at this point you would find that nothing happens because the field in question is actually on a hidden page (the Postbacks page). It turns out the field is in fact activated - highlighted and focus even goes there, but because the tab is not active that fact is lost to you as the user of the page - to you it appears that nothing happens.

So how can this be fixed?

West Wind Web Connection 5.37 includes a new client static side event called OnBindingErrorLink that is fired when you click on the error link. This allows you some control over what happens in the event of a link click so you can optionally take over the link management and either inject your own processing and let the default behavior still take place or override the behavior completely.

The following implementation activates a tab page if the control that has the error is contained on one:

function OnBindingErrorLink(errorCtl)
{
    var control = errorCtl;
 
    // *** Find the parent 'tab' page id
    while(control.parentNode)
    {    
        control = control.parentNode;
        if (!control)
            break;            
        if (control.id.substr(0,4) == "page")
        {                        
            ActivateTab("Tabs",control.id);
            return;
        }
    }    
}

This code is not totally generic - it makes the assumption that the <div> tags that are the tab content have an ID that starts with "page"  (ie. pageInformation,pageSelection etc.). Here's what the page markup looks like:

<ww:wwWebTabControl runat="server" id="Tabs" SelectedTab="pageSelection">
      <TabPages>
          <ww:wwWebTabPage runat="server" id="Page1" TabPageClientId="pageInfo" 
Text=" Information" TabImage="/wconnect/images/info.gif" Style="text-align:left;" > </ww:wwWebTabPage>
          <ww:wwWebTabPage runat="server" id="Page2" TabPageClientId="pageSelection" Text="Selection"></ww:wwWebTabPage>
          <ww:wwWebTabPage runat="server" id="Page3" TabPageClientId="pagePostBack" 
Text=" PostBacks" Tabimage="/wconnect/images/help.gif" style="text-align:left"></ww:wwWebTabPage>
          <ww:wwWebTabPage runat="server" id="Page4" TabPageClientId="pageDisplay" Text="Display"></ww:wwWebTabPage>
          <ww:wwWebTabPage runat="server" id="Page5" TabPageClientId="pageDisplay" 
Text="Disabled" Enabled="false"></ww:wwWebTabPage>           
          <ww:wwWebTabPage runat="server" id="Page6" TabPageClientId="pageSamples"  Text="Samples"></ww:wwWebTabPage>
      </TabPages>
  </ww:wwWebTabControl>

 
  <div id="pageInfo" class="blackborder tabpage" style="display: none">
      <h3>The Tab Control</h3>
      ... 
</div>
 
  <div id="pageSelection" class="blackborder tabpage" style="display: none">
      <h3>Tab Page Selections</h3>
      ...
  </div>
 
  <div id="pagePostBack" class="blackborder tabpage" style="display: none">  
      <h3>Postback to Server</h3>
      ...
  </div>

Based on this layout the OnBindingErrorLink function is passed the DOM element that has the error - ie. a textbox, listbox or checkbox. The code then searches up the DOM hierarchy from this element to see if the item is on a tab page - if a tab page is found, it's activated with a call to ActivateTab().

As mentioned this code isn't entirely generic - there's no completely generic way to detect a tab page by searching backwards. The above works as long as the page DIVs are prefixed with a "page" string as above. Another alternative is to always use a specifc CSS class and then use jQuery and the $(this).hasClass("tabpage") to check for a specific CSS class that is applied.

Lots of options, but when you are using TabPages this is something that you probably need to deal with one way or another.

Posted in:

Feedback for this Weblog Entry