This is a Servoy tutorial that demonstrates how to add a form to a tab panel using a map. It’s a useful technique for controlling exactly where the new form should be placed among other forms in the tab panel, that may or may not be showing.
In the real-world, users click options, and depending on the option, a new form may need to be added to the a tab panel that will contain all the relevant information. For example, assume we are working on a contact record that has a tab panel showing additional information in the lower half of the layout. If the user clicks an option to set the contact type to “Sales Rep”, then maybe a new form should be added to the tab panel that contains additional info for sales reps, like commission, territory, etc. However, the new form typically needs to appear in a logical position, and not just get added to the end. It also should not be there if the contact type is not a sales rep. This is where a tab panel map comes into play.
A tab panel map is nothing more than a literal array with tab names. The tab names are added to an array in the logical order that we would want them to appear, and not in alphabetical order. For example, maybe the sales rep tab should be shown after the address tab, but before the comments tab. I have seen all kinds of implementations to do this, but nothing could be simpler then just using a simple map of names in the order you want.
Shown below is how to setup a map for a tab panel with the tab names you are going to use, and in the logical order you want them to appear. In our example, we are using i18n keys for the tab names.
1 2 3 4 5 6 | var _tabMap = [ i18n.getI18NMessage("lbl.tabD"), i18n.getI18NMessage("lbl.tabC"), i18n.getI18NMessage("lbl.tabA"), i18n.getI18NMessage("lbl.tabB") ]; |
The utility method shown below is used to add a tab form to a tab panel. It accepts all the necessary parameters, ensures the tab does not already exist, and adds it immediately after the first tab that comes before it in the tab map. If no existing tab is found that comes before the new tab being inserted, then the new tab is inserted at the end. Using this utility, tabs will be inserted precisely according to the tab map, regardless of the order in which they are added.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | /** * Add a tab according to the tab map * * @author Gary Dotzlaw - Dotzlaw Consulting * @since 2013-11-23 * * @param {String} sForm - The base form to add the tab to (where the tab element is) * @param {String} sTab - The name of the tab * @param {String} sTabForm - The name of the tab form to be added * @param {String} sTabLabel - The label for the tab (i18n key like "lbl.tabName") * @param {String} sTabRelation - The relationship for the tab * @param {Array} aTabMap - The map for tab order (uses sTabLabel for key) * * @return {Boolean} TRUE or FALSE */ function utils_tabAdd(sForm, sTab, sTabForm, sTabLabel, sTabRelation, aTabMap) { var i = 0, k = 0, iMax = forms[sForm].elements[sTab].getMaxTabIndex(), bTab = false, aCurrentTabLabels = [], iFoundIndex = -1, bFound = false, sCurrentTabLabel = ""; // Get the all the tab names that exist for (i = 1; i <= iMax; i++){ aCurrentTabLabels.push(forms[sForm].elements[sTab].getTabTextAt(i)); // Check to see if the tab we want to add already exists if (i18n.getI18NMessage(sTabLabel) == aCurrentTabLabels[i-1].replace(/ /g, " ")) bTab = true; } // Tab was not found, so we need to add it var iTabIndex; if (!bTab && aTabMap){ // Find where it is supposed to be in the tab map iTabIndex = aTabMap.indexOf(i18n.getI18NMessage(sTabLabel)); // Now search to find any tab that is supposed to be before this one, and insert the new tab after it for (k = iTabIndex; k >= 0; k--){ if (!bFound){ iMax = aCurrentTabLabels.length; for (i = iMax; i >= 1; i--){ // Clean up the tab name for webclient sCurrentTabLabel = aCurrentTabLabels[i-1].replace(/ /g, " "); if (sCurrentTabLabel == aTabMap[k]){ iFoundIndex = i; bFound = true; break; } } } } if (iFoundIndex > -1){ // Add the new tab at the found location bTab = forms[sForm].elements[sTab].addTab(forms[sTabForm], null, i18n.getI18NMessage(sTabLabel), null, null, null, null, sTabRelation, iFoundIndex); } } if (!bTab){ // A tab that the new one needs to go after was never found, so add it to the end bTab = forms[sForm].elements[sTab].addTab(forms[sTabForm], null, i18n.getI18NMessage(sTabLabel), null, null, null, null, sTabRelation, forms[sForm].elements[sTab].getMaxTabIndex() + 1); } return bTab; } |
This utility is used to simply remove the tab panel by i18n key. Nothing complicated here at all; it simply loops through the tabs and deletes the right one, or exits if it is not found.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | /** * Remove a tab * * @author Gary Dotzlaw - Dotzlaw Consulting * @since 2013-11-23 * * @param {String} sForm - The base form to remove the tab from (where the tab element is) * @param {String} sTab - The name of the tab element * @param {String} sTabLabel - The name of the tab form to be removed (i18n key like "lbl.tabName") * * @return {Boolean} TRUE or FALSE * * @properties={typeid:24,uuid:"8AD5AD48-466D-41C1-81AD-7134FFBD5B94"} */ function utils_tabRemove(sForm, sTab, sTabLabel) { var sCurrentTabLabel = "", i = 0, iMax = forms[sForm].elements[sTab].getMaxTabIndex(), bTab = false; for (i = 1; i <= iMax; i++){ // Clean up the tab name for webclient sCurrentTabLabel = forms[sForm].elements[sTab].getTabTextAt(i).replace(/ /g, " "); // If we find the tab we are looking for, then remove it if (sCurrentTabLabel == i18n.getI18NMessage(sTabLabel)){ bTab = forms[sForm].elements[sTab].removeTabAt(i); } } return bTab; } |
This is how to add a tab panel by name using the map, and also how to remove a tab panel by name (or i18n key).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | utils_tabAdd( "myParentForm", "myTabPanelName", "myTabForm", "lbl.tabC", "myRelationParentToTab", _tabMap ); utils_tabRemove( "myParentForm", "myTabPanelName", "lbl.tabC" ); |
I hope this Servoy tutorial was helpful and gives you a new way of adding forms to tab panels based on a map of tab names. I have used this technique over and over again in my projects. Add the utility methods to your library and put it to good use. It will help you get your user interface under control by allowing you to move groups of optional data onto tab panels, allowing them to be added or removed based on options selected.