Reference: Dynamic Tabs UI Shell Template Functional UI Pattern

This topic contains the following sections:

Overview

The Dynamic Tabs UI Shell Template (UI Shell) is used to address one of the necessary attributes of a software product: usability. Elements addressed are:

  • Provide common locations for basic functions and features
  • Promote “discoverability” of features through visual affordances and common user gestures
  • Provide timely and relevant information supportive of users’ goals and tasks.
  • Maximize use of screen real estate to provide information within the context of users’ goals and tasks and avoid needless navigation
  • Make use of emerging UI technology

The UI Shell is a template with behaviors. Commonly provided behaviors aid predictability and control -- attributes of usability. These behaviors center around navigation. When implemented essentially the same across the application, the application feels predictable. The user feels in control.

The most salient behavior supported by the UI Shell is dynamic tabs. The tabs are dynamic in that they are rendered and dismissed upon demand by the user.

The ADF UI shell page template contains facets, attributes, ADF components, and a Java Bean to provide behavior. Multiple ADF page fragments (defined as bounded taskflows) run in a series of dynamic tabs on the page. A page fragment is a JSF JSP document (.jsff) that can be rendered as content of another JSF page. It is similar to a page, except that it cannot contain elements such as <f:view>. The template itself manages the dynamic tabs; allows facilities to open new tabs with given taskflow identifiers; and handles dirty state for those tabs. The template handles a maximum of 15 taskflows represented as tabs.

The template defines four areas with ten facets in a generally described 3 rows by 2 column layout. The UI Shell is one of two templates provided "out-of-the-box" from Oracle. It is called "Dynamic Tab Shell." Any newly created JSF or JSP page can be based on this template.

Problem Description

A chief challenge in UI development is rational consistency -- providing the user with predictable locations and behaviors for the most salient features. Because the ADF UI Shell is a template, it provides guidance for development teams to deliver a consistent UI to their customers. The primary assumption of the UI Shell is that each page based on the template will represent a significant module of an application, if not separate applications. As a consequence, the "boilerplate" portion of the UI (e.g., branding, ubiquitous controls, obligatory legal statements) are more easily held consistent in form, placement, and function -- as they are defined once per page. The more interactive portion of the application, that content which delivers the features and functions that define the application, are presented in the "workarea" of the template. The UI Shell identifies those areas through named facets (e.g., navigation) and regions (e.g., dynamic tabs). Nearly all, if not all, of the product's value add can be surfaced in these areas within a single page as bounded ADF taskflows containing one or more ADF page fragments.

Navigation rules between applications represented as single pages can be defined in unbounded ADF taskflows and presented to the user as global navigation controls (e.g., global tabs, buttons, links) providing convenient access to a suite of separate, but related products.

Technical Pattern Description

The UI Shell template and Java bean is contained within an ADF jar shipped with JDeveloper/ADF. The Java bean has a list of methods (i.e., APIs) available only to this template. The UI layout of the template has ten named facets. The template also has nine attributes which pass in values to each page based on the template. There are also embedded components to round out the Look and Feel (L&F) of the template.

Facet Name Description
globalLinks Links that appear in the top right hand corner of the page are placed here -- just to the left of status facet. Global Links provide access to content that is applicable on almost every page of an application. They are typically outside the navigational hierarchy or structure of the application. Examples include Preferences, Help, and Sign Out.
status Location where user account information is presented.
globalToolbar Located above the globalTabs facet, this should contain UI elements for actions that affect the entire page (such as adding or removing a global tab).
globalSearch Flushed right of the globalToolbar facet, it can be used to provide the input area for a global search.
globalTabs This facet should contiain the top most tabs of the page. An af:navigationPane which is either bound to an xml menu model or contains af:commandNavigationLinks to traverse the site or intranet would be a good choice for this area. These tabs are not part of the template and are thus not managed by the template. For example, each tab is a separate page or page template.
innerToolbar A location for toolbar content that is placed between the global tab and the inner content region (e.g., the dynamic tabs). This should contain UI elements for actions that affect the dynamic tabs (such as adding or removing a tab).
welcome Content in this facet is displayed before any tabs are launched and after all tabs (i.e., taskflows) are closed.
navigation The left hand side area of the page template. This section usually contains a taskflow with links that can launch new dynamic tabs also containing taskflows.
copyright This area should contain the copyright text that will show up in the bottom left hand corner of the page. If needed, this facet can contain additional content, such as other legal notices, as this area will stretch to accommodate its contents.
about This section covers the bottom left hand corner of the page. It can contain any content, but is typically used to describe the product (e.g., version number), the vendor, and policies (e.g., terms of use, privacy) through a series of links to those pages.
Attribute Name Description
logoImagePath The image path to use for the logo. If this is absent, the Oracle logo will be used.
brandingTitle The title used in the top left next to the logo. This should be the main title for this page -- describing the product or suite represented in the page.
statusWidth The amount of horizontal space given for the text in the status facet. The default is 200px.
headerSplitterPosition The amount of vertical space that should be given to the branding area of the page. The header section is composed of the logo, title, global links, and status areas. This defaults to 30px from the top.
headerSplitterDisabled Enables a splitter control whereby the user can resize the branding area. The default is false.
globalSplitterPosition The amount of vertical space that should be given to the global section of the page. The global section is composed of the global toolbar and global search areas. The default is 25px from the bottom of the headerSplitterPosition attribute.
navSplitterPosition The amount of horizontal space that is given to the navigation area and is thus space taken away from the dynamic tab content region. The default is 200px from the start (e.g., left).
navSplitterDisabled Enables a splitter control whereby the user can resize the navigation area. The default is true.
legalAreaPosition The amount of vertical space that should be given to the legal area of the page. The legal section is composed of the copyright and about areas. The default is 20px from the bottom.
dirtyTabPopupTitle When there is a request to close a tab that is dirty, a popup dialog warns the user about whether or not to continue closing the tab (i.e., taskflow). The title for the dialog is specified by this attribute.
dirtyTabPopupText When there is a request to close a tab that is dirty, a popup dialog warns the user about whether or not to continue closing the tab (i.e., taskflow). The text for the dialog is specified by this attribute.
tooManyTabsPopupTitle When the maximum number of tabs (i.e., taskflows) is reached, and an additional tab is requested, a popup dialog informs the user of that limit. The maximum number of tabs the template allows is 15. The title for the dialog is specified by this attribute.
tooManyTabsPopupText When the maximum number of tabs (i.e., taskflows) is reached, and an additional tab is requested, a popup dialog informs the user of that limit. The text for the dialog is specified by this attribute.
Component Description
Branding Bar A series of nested layout components, style classes, images, components and aforementioned facets to provide space efficient customizable branding for the application.
Status Indicator Displays various icons (animated and static) to indicate server activity. The icons for the status indicator component are set in the skinning (CSS) file.
Panel Splitters Components that partition the page into its five areas: header, global, navigational, local, and legal. The allocation between the navigational and local area is adjustable at runtime by the user via s splitter control if its value is set to the default value of true.
Decorative Boxes Provides a bordered look (i.e. rounded corners). It act as a L&F transition between areas on a page. For example, a page that has a dark background for its template can use the decorative box to transition to a white background for its local content area. It is bordered by eight styled areas that are controlled using skinning keys.
Close icon Aligned right of the dynamic tabs, this icon appears when the number of open task flows within a tab is greater than one. Clicking this icon (X) closes any selected tab that is in a clean vs dirty state. Enabled, mouseover, mousedown, and mouse up states are provided "Out of the Box" for this control.

Java APIs

The behaviors of the template are provided through a class called TabContext. TabContext contains methods to launch new tabs, as well as other forms of manipulation of the tabs. The best practice to leverage the APIs within TabContext is through a managed bean written in Java.




/* Copyright (c) 2008, 2009, Oracle and/or its
 affiliates. All rights reserved. */
 import oracle.ui.pattern.dynamicShell.TabContext
 TabContext tabContext = TabContext.getCurrentInstance();
  

All public APIs are EL accessible.

The addTab API will always launch new tabs into the local content area. This API is appropriate for use cases where multiple instances of the same task flow are desired to each have a separate tab, such as "create new."

  1. /*Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. */
  2. try
  3. {
  4. tabContext.addTab("Some Localized Title of the Tab","/path/to/taskflow#taskflowId");
  5. }
  6. catch (TabContext.TabOverFlowException toe)
  7. toe.handleDefault();
  8. }

Line 6 can throw a TabOverFlowException. This will occur if there is an attempt to open more than the maximum number of available tabs (i.e., taskflows) at run time. This case can be handled in any way preferred or use the handleDefault() method to call a popup warning dialog to appear to the user. When this exception is thrown, the requested tab will not open for the user. The maximum number of tabs the UI Shell allows is 15.

The addOrSelectTab API will always launch one instance of the tab by detecting whether it has already launched. If so, that tab is selected instead. This API is appropriate for use cases where a single instances of a task flow is desired with a tab, such as "edit object." If the taskflow for that object is open, then a gesture by the user to re-launch that edit object taskflow will return selection to its tab.





/*
Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */
try
{
 tabContext.addOrSelectTab("Some Localized Title of the Tab",
 "/path/to/taskflow#taskflowId");
}
 catch   (TabContext.TabOverFlowException toe)
{
 toe.handleDefault();
}
 

There are use cases where the goal is not to use tabs (i.e., present the user with two or more task flows launched serially within tabs) but to have a single "replace-in-place" UI. In this UI, tabs are absent, the opened task flow occupies the entire local content region of the page. The tabContext.setMainContent API provides for that use case.





/*
Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */
 tabContext.setMainContent("/some/path/to/taskflow#taskflowId");
 

Note: The single task flow (i.e., replace-in-place) and tabbed task flow cannot be used concurrently on the same page. An attempt to call this API when tabbed task flows are showing or an attempt to launch a new tabbed task flow when the content region is showing, will result in an exception. It also makes for poor UI.

In addition to the Close icon which presence and behavior are provided automatically by the ADF UI Shell template, tabs and their task flows can be closed programmatically (e.g., from within the task flow) via the removeCurrentTab API.



/*Copyright (c) 2008, 2009, Oracle and/or its
affiliates. All rights reserved. */

 tabContext.removeCurrentTab();
 

Both the Close icon embedded with the UI Shell template and the removeCurrentTab method will check whether the taskflow within the selected tab is clean or dirty. Presently the model could be checked for dirty state; however, the model does not track how it was made dirty (e.g., the current task flow or another). What this template provides at the ADF View level is the markCurrentTabDirty API to indicate that the current task flow is dirty by setting the style of the tab label to italic. This API could be triggered by a custom method that listens for a value change on the task flow shown within the tab. Conversely, after any changes have been committed (e.g., saved to DB), this same API could be called to indicate a clean task flow by setting the style of the tab label back to normal.



/*Copyright (c) 2008, 2009, Oracle and/or its
affiliates. All rights reserved. */

tabContext.markCurrentTabDirty(true);
 

By passing in false to the markCurrentTabDirty API, the tab label style is set to normal.

As mentioned previously, both the embedded Close icon and the removeCurrentTab API will check whether the current tab (i.e., task flow) is clean or dirty. However, there may be cases where there is a need to check whether the state of the current tab or any open tab is dirty (e.g., prior to page navigation). The isCurrentTabDirty or isAnyTabDirty API could check for the corresponding case before navigating.



/*Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. */

// check the dirty state of the current tab

 boolean isCurrentTabDirty = tabContext.isCurrentTabDirty();

// check the dirty state of all the tabs (will return true if any tab is dirty)

 boolean isAnyTabDirty = tabContext.isTagSetDirty();
 

Note that when typing to reference for this method directly isTagSetDirty has an unexpected spelling.

There are use cases where it is important to know if any tabs are visible in the UI. For example, the UI may call for a particular toolbar item to enable or render when one or more tabs are present. The embedded Close icon exhibits this behavior automatically -- it renders when one or more tabs appear. The selectedTabIndex API can use the Rendered or Disabled property of any UI construct for that purpose.



/*Copyright (c) 2008, 2009, Oracle and/or its
affiliates. All rights reserved. */

 tabContext.selectedTabIndex();
 

The tab index is zero based. So if any tabs are present, the value of selectedTabIndex would be zero or greater.

To access TabContext methods from within a task flow, define a parameter for TabContext in the task flow. The UI Shell template passes in TabContext.

Element Value
name tabContext
class oracle.ui.pattern.dynamicShell.TabContext
required true

The task flow XML file should look similar to this.



<input-parameter-definition> 
  <name>tabContext</name> 
  <class>oracle.ui.pattern.dynamicShell.TabContext</class> 
  <required/> 
</input-parameter-definition> 
 

This places the TabContext in the pageFlowScope.

The User Experience

The UI Shell has four principle areas or partitions. Each will be discussed in turn and illustrated in summary.

Global Area

The global area extends across the full width at the top of the UI Shell. It provides a consistent and persistent context for the user. It is the portion of the template "boilerplate" that provides the user with a sense of place. It should contain the UI controls that in general drive the contents of the other two "work" areas of the UI. Facets and attributes are provided in this area to suggest what those UI controls and displays should be, including: Logo, Branding Bar, Global Links, Global Toolbar, Global Search, and Global Tab.

Navigational Area

The navigational area uses either the navigation facet (e.g., left pane of the UI shell) or the innerToolbar facet (tool bar placed between the global tab and the inner content region). It can have controls that, in general, drive the contents of the local area. In other words, users should get the sense, after extended use of an application, that the navigational area controls act upon the local area and its contents.

Local Area

The local area is in the center of the UI Shell. Its where the user performs the bulk of the tasks. In other words, it is the main work area and typically takes a transactional form with UI controls and displays. Consequently, the splitter that divides the left pane navigational area from the local area was designed to favor the local area. That is, out of the box, significantly more real estate is allocated to the local area and, by default, the splitter closes to the left (i.e., all remaining space is allocated to the local area). The dynamic tabs method or the single replace-in-place method of presenting task flows is articulated in the local area Tab Methods .

Legal Area

The legal area extends the full width of the UI Shell at the bottom. It is the portion of the template "boilerplate" where legal notices, statements, and policies relevant to the application can appear. Like the global area, it can contain UI controls that navigate to other locations. Facets are provided in this area to suggest what those UI controls and displays should be, including, Copyright, About, Privacy, and so forth.

Runtime Example of the Four Principle Areas of the UI Shell

Launch Methods

Task flows can be launched by any UI construct into the local area via APIs provided by the ADF UI Shell template. In this pattern, three different examples of those constructs are given and illustrated: left hand side (LHS), inner toolbar, and from within a task flows.

When the user selects a link or button in the LHS pane, a taskflow opens in the Local Area.

Example of Launch from Left Hand Side Panel

Alternatively, the user can select a menu item or toolbar option to open a taskflow into the Local Area.

Example of Launch from Inner Toolbar

The last described alternative launch method is the user selecting a UI control in the current taskflow that launches a subsequent taskflow in the local area.

Example of Launch from within a Taskflow

Close Methods

Task flows can be closed by APIs provided by the ADF UI Shell template. Three different examples of those constructs are given: Embedded Close Icon; Inner Toolbar Close option, and Close Button Within the Task Flow Example.

The embedded (no additional coding required) close icon renders on the same horizontal plane to the far right of the page when a taskflow is opened within a tab. The user activates the close icon on the selected taskflow (i.e., tab) which is dismissed from view.

Example of Embedded Close Icon

With the inner toolbar close option, the user activates a close menu or toolbar item on the selected taskflow (i.e., tab) which is then dismissed from view.

Inner Toolbar Close Option Example

A close button within the UI of the taskflow allows the user to dismiss that taskflow in the local area prior to or at the conclusion of the taskflow. Of course, the taskflow could "auto-dismiss" at the conclusion of a taskflow. However that is "bad" UI. The opening and closing of a user's task within a taskflow should always be under the control of the user.

Close Button Within the Task Flow Example

Dirty" & "Clean" State Indication

When the state of user data changes within a task flow, that state change is indicated by changing the text style of the tab label from normal to italic (e.g., the Next Activity). This is most affective in UIs where the user will alternate between several taskflows across multiple tabs in the process of completing a task (e.g., copy data between task flows). In so doing, it would be helpful to remind the user -- particularly after a task interruption -- of which taskflow has changed data (i.e., dirty).

Example of A Tab Showing Dirty State

When all changed user data is committed (i.e., saved) the taskflow is "clean." At that point, the text style of the tab label toggles from italic to normal.

Example of A Tab Showing Clean State

When the user attempts to close a task flow and the state of that task flow is "dirty", the user will receive a warning that the pending action could result in data loss. At that point the user should have a choice of one of two options.

  1. Continue with the pending action and lose recent data updates
  2. Cancel the pending action and return to save recent data updates

Both options are viable to the user. In the first case, the user has made changes for which there is a desire to abandon. In the second case, the user may have inadvertently or unwittingly triggered a close on the task flow for which there is no desire to abandon recent changes.

The unsaved data warning that the user receives automatically at run time is a feature of the UI Shell in cases where it is a tab that is being closed while in a dirty state. Note. This feature is not available for cases outside of this template.

This feature should not be confused with the unsaved data warning on page navigation. That feature is not automatic but must be enabled at design time (DT) on a page by page case (e.g., each page based on the UI Shell template). When enabled, it provides a warning to the user in cases of navigation at the page level -- as oppose to the region level -- where pending changes have not been committed and the state of the page will be reset. In this case as well, the user has made changes for which there is a desire to abandon; or, the user inadvertently or unwittingly triggered a close at the page level for which there is no desire to abandon recent changes. The warning dialog presented in this case affords the user the same two choices. This feature is available in all cases, that is, with or without the use of the UI Shell template. For a description of how to enable this feature read the Warning on Unsaved Changes Functional UI Pattern on OTN at https://www.oracle.com/application-development/technologies/adf/unsaveddatawarning.html.

Tab Methods

The UI Shell Template supports two tab methods: dynamic tabs or no tabs.

Dynamic tabs lets the user spawn new tabs for each taskflow instance and then closing it when, for example, the task has been completed. Taskflows can be launched within dynamic tabs by any UI construct (e.g., left hand side pane, toolbar, from within another taskflow). The tabs are dynamic in the sense that the tabs appear to the user when the contained task flow is launched and disappear when the contained task flow is closed.

Multiple instances of the same bounded taskflow can open in dynamic tabs. Create New is a typical use case where multiple instances of the same bounded taskflow is desired.

More typically, a single instance of a bounded taskflow opens in an dynamic tab. In the first invocation of taskflows of this type, a tab containing that taskflow appears. Any subsequent invocation of any of those taskflows, while they remain open, shifts the selected state to that taskflow.

Finally, there is the option of a replace-in-place single instance bounded taskflow. In the first invocation of a taskflow of this type, a single instance taskflow appears occupying the entire local content area (i.e., no tab). Any subsequent invocations of any taskflow results in a replace-in-place user experience (i.e., the subsequent taskflow also occupies the entire local content area replacing the previous taskflow). Note : This method can only be used exclusively of the other two (i.e., Dynamic Tabs for Multiple Instances and Dynamic Tabs for Single Instances) per page.

Too Many Tabs Warning Dialog

When the requested number of open task flows (i.e., tabs) exceeds the maximum allowed by the UI Shell (15), the user will automatically receive a "too many tabs" warning dialog. The dialog title text and body text are attributes of the UI Shell and can be specified at design time.

Detecting the Presence of Tabs

It is possible to determine if any tabs are open in the UI. This is useful for enabling or rendering any UI construct that has either the Disabled or Rendered property. The Close icon is an example use of this API. It is not rendered until one or more tabs are present. One example would be to enable/disable menu items at the presence or absence of tabs. Another would be to render or hide toolbar buttons at the presence or absence of tabs or taskflows.

Adding a Welcome Page

Often an application will have an introductory, "start", or "welcome" page. This can be the default UI for the user visiting the application. The UI Shell template has a single facet that can be used for this purpose. It is identified as the welcome facet. Content within the welcome facet displays when no other content (e.g., taskflows) are open on the page. Thus, its content appears as default when the page is displayed or when all taskflows are closed.

Pattern Implementation

To recreate the demonstration application used to illustrate the UI Shell template, follow the steps below. The implementation of this demonstration is divided into 5 major steps.

  1. Specify the Control Flow Cases between the pages in adfc-config. Users will activate a Control Flow Case via a Global Tab.
  2. Create jsp pages based on the UI Shell template.
  3. Create the jsp page fragments and task flows that will contain them for the demonstration application.
  4. Create a managed bean that will call each of the the taskflows to demonstrate the public APIs available in TabContext class.
  5. In the pages and page fragments add EL bindings to the managed bean calling taskflows as dynamic tabs.

Create Application Workspace

To start the development of a demonstration application:

  1. Select the New icon to create a new application workspace.
  2. There will be no need for the Model project in this sample.
  3. In the New Gallery dialog, select Fusion Web Application(ADF) from the Application Category.
  4. Click Ok
  5. In the Create Fusion Web Application wizard, type UIShell or other appropriate name for the Application Name.
  6. For project names, type uiShellModel and uiShellViewController for the Model and ViewController respectively, or other appropriate names.
  7. For Application Package Prefix, type src or other appropriate prefix.
  8. Click Finish.

Create the Demonstration Application Unbounded Task Flow

The demonstration application is composed of three jsp pages, each represented as a global tab.

Create the Page Flow for the Global Tabs

The Control Flow Cases between the pages will be specified in the adfc-config.xml file.

  1. Open the adfc-config.xml file.
  2. From the Component Palette, drag and drop 3 View Activities onto the diagram.
  3. Rename them First , Second , and Third , respectively.
  4. From the Component Palette, drag and drop the Wild Card Control Flow Rule.
  5. Leave the wildcard control flow rule with a single wildcard character (*), indicating that control can pass to the activities connected to it in the task flow diagram from any activity within the task flow.
  6. Select a Control Flow Case from the Component Palette and add a case from the wild card control flow rule to the First activity.
  7. Label the case First .
  8. Select a Control Flow Case from the Component Palette and add a case from the wild card control flow rule to the Second activity.
  9. Label the case Second .
  10. Select a Control Flow Case from the Component Palette and add a case from the wild card control flow rule to the Third activity.
  11. Label the case Third .
  12. Save the file.

When completed, the adfc-config.xml diagram should appear as illustrated.

Illustration of page flow for global tabs

Create JSP Files Based on the UI Shell Template

Each page will be created based on the UI Shell template in turn. Although not fully illustrated here, each page is assumed, in practice, to represent a single application to the user. The goal here is to create three pages whereby major features and UI methods offered by the UI Shell template can be demonstrated.

Creating Pages

In this section, each page associated with each view activity will be created in turn, starting with First.

  1. In the adfc-config.xml file, create the First page by double-click on the First view activity.
  2. Type First.jspx for the File Name.
  3. Select the Page Template radio control.
  4. Select the Oracle Dynamic Tabs Shell.
  5. Click Ok.

    The DT view of the UI Shell template should appear in the Visual Editor.

  6. In the Structure Window, expand the tree to reveal the document node. Select it.
  7. In the Common section of the Property Inspector, type First Page for the Title property.
  8. Save the page.

Create the page associated with the Second view activity.

In this section, the page associated with the second view activity will be created, called Second.

  1. In the Editor pane of the IDE, select the tab for the adfc-config.xml file.
  2. In the adfc-config.xml file, create the Second page by double-click on the Second view activity.
  3. Type Second.jspx for the File Name.
  4. Select the Page Template radio control.
  5. Select the Oracle Dynamic Tabs Shell.
  6. Click OK.

    The DT view of the UI Shell template should appear in the Visual Editor.

  7. In the Structure Window, expand the tree to reveal the document node. Select it.
  8. In the Common section of the Property Inspector, type Second Page for the Title property.
  9. Save the page.

Create the page associated with the Third view activity

In this section, the page associated with the third view activity will be created, called Third.

  1. In the Editor pane of the IDE, select the tab for the adfc-config.xml file.
  2. In the adfc-config.xml file, create the Third page by double-click on the Third view activity.
  3. Type Third.jspx for the File Name..
  4. Select the Page Template radio control.
  5. Select the Oracle Dynamic Tabs Shell.
  6. Click OK.

    The DT view of the UI Shell template should appear in the Visual Editor.

  7. In the Structure Window, expand the tree to reveal the document node. Select it.
  8. In the Common section of the Property Inspector, type Third Page for the Title property.
  9. Save the application.

Add Global Tabs to Each Page

UI tabs are added to allow the user to navigate between pages of the application. There are three pages in this sample application.

To add global tabs to the first page:

  1. In the Editor pane of the IDE, select the tab for the page First.jspx.
  2. In the Structure Window, expand the tree to reveal the globalTabs facet. Select it.
  3. Alternatively, select the globalTabs facet in the Visual Editor.
  4. In the Layout section of the Component Palette, select the Navigation Pane component to insert it into the globalTabs facet.
  5. In the Common section of the Component Palette, select the Navigation Item to insert it into the Navigation Pane.
  6. In the Common section of the Property Inspector, type First for the Text property.
  7. In the Behavior section of the Property Inspector, change the Selected property to true .
  8. From the Component Palette, drag and drop another Navigation Item onto the Navigation Pane in the Structure Window.
  9. In the Common section of the Property Inspector, type Second for the Text property.
  10. In the Navigation sub-section of the Common section in the Property Inspector, select second from the Action property drop down.
  11. From the Component Palette, drag and drop another Navigation Item onto the Navigation Pane in the Structure Window.
  12. In the Common section of the Property Inspector, type Third for the Text property.
  13. In the Navigation sub-section of the Common section in the Property Inspector, select third from the Action property drop down.
  14. Save the page.

To add global tabs to the second page:

  1. In the Editor pane of the IDE, select the tab for the page Second.jspx.
  2. Select the globalTabs facet in the Visual Editor.
  3. In the Layout section of the Component Palette, select the Navigation Pane component to insert it into the globalTabs facet.
  4. In the Common section of the Component Palette, select the Navigation Item to insert it into the Navigation Pane.
  5. In the Common section of the Property Inspector, type First for the Text property.
  6. In the Navigation sub-section of the Common section in the Property Inspector, select first from the Action property drop down.
  7. From the Component Palette, drag and drop another Navigation Item onto the Navigation Pane in the Structure Window.
  8. In the Common section of the Property Inspector, type Second for the Text property.
  9. In the Behavior section of the Property Inspector, change the Selected property to true .
  10. From the Component Palette, drag and drop another Navigation Item onto the Navigation Pane in the Structure Window.
  11. In the Common section of the Property Inspector, type Third for the Text property.
  12. In the Navigation sub-section of the Common section in the Property Inspector, select third from the Action property drop down.
  13. Save the page.

To add global tabs to the third page:

  1. In the Editor pane of the IDE, select the tab for the page Third.jspx.
  2. Select the globalTabs facet in the Visual Editor
  3. In the Layout section of the Component Palette, select the Navigation Pane component to insert it into the globalTabs facet.
  4. In the Common section of the Component Palette, select the Navigation Item to insert it into the Navigation Pane.
  5. In the Common section of the Property Inspector, type First for the Text property.
  6. In the Navigation sub-section of the Common section in the Property Inspector, select first from the Action property drop down.
  7. From the Component Palette, drag and drop another Navigation Item onto the Navigation Pane in the Structure Window.
  8. In the Common section of the Property Inspector, type Second for the Text property.
  9. In the Navigation sub-section of the Common section in the Property Inspector, select second from the Action property drop down.
  10. From the Component Palette, drag and drop another Navigation Item onto the Navigation Pane in the Structure Window.
  11. In the Common section of the Property Inspector, type Third for the Text property.
  12. In the Behavior section of the Property Inspector, change the Selected property to true .
  13. Save the page.

Create Page Fragments and Taskflows

Taskflows can be called by contextual events from the navigational area to be rendered in the local content area. A taskflow may also be called from another taskflow within the local content area. In both cases, the result could be a taskflow within a dynamic tab (i.e., single instance, multiple instance) or within a replace-in-place panel that occupies the entire local area. Taskflows themselves could be comprised of a single page fragment or multiple page fragments. In either case, taskflows are bound and as a collection can present nearly all, if not all, of the value add defining an application.

For demonstrations purposes only, four taskflows will be created. Each will contain a single page fragment.

  • One taskflow will be created to demonstrate dynamic tabs of multiple instances.
  • Three taskflows will be created to demonstrate dynamic tabs of single instances.
  • Two of the three taskflows will be re-used to demonstrate replace-in-place single instances with no tabs.

Create taskflow to use as multiple instance

To create the taskflow to demonstrate dynamic tabs of multiple instances:

  1. Open a context menu on uiShellViewController.
  2. Select New.
  3. In the New Gallery under Web Tier, select the JSF category.
  4. On the right hand side, select the ADF Task Flow.
  5. In the Create Task Flow dialog, type new.xml for the task flow File Name.
  6. In the Directory field, append the path to read: C:\JDeveloper\mywork\UIShell\uiShellViewController\public_html\WEB-INF\flows

    This is a convenience to improve the workspace organization.

  7. Click OK.
  8. Drag and drop a view activity onto the task flow diagram.
  9. Change the name to multiple .
  10. Open the multiple view activity (e.g., double-click).

    This should result in the Create New JSF Page Fragment dialog in the Directory field, append the path to read:

    C:\JDeveloper\mywork\UIShell\uiShellViewController\public_html\fragments . This is a convenience to improve the workspace organization.

  11. Click OK to accept defaults.
  12. In the Layout section of the Component Palette, select the the Panel Group Layout component to insert it into the page fragment.
  13. In the Common section of the Component Palette, select the Output Text component to insert it into the the Panel Group Layout.
  14. In the Common section of the Property Inspector, type This is a new activity! for the Value property.
  15. In the Style section of the Property Inspector, type the following for InlineStyle: color:Purple; font-size:x-large; font-weight:bold;
  16. From the Layout section of the Component Palette, drag and drop the Panel Accordion component onto the the Panel Group Layout.
  17. Select the showDetailItem component nested within the Panel Accordion in the Structure Window.
  18. Change the Text property to First Steps .
  19. In the Layout section of the Component Palette, select the Panel List component to insert it into the Show Detail Item.
  20. In the Common section of the Component Palette, select the Output Text component three times to insert 3 instances into the Panel List.
  21. Add Step 1: Do something , Step 2: And then something else , Step 3: Be happy! for the Value property of each Output Text component, respectively.
  22. From the Common section of the Component Palette, drag and drop the Show Detail Item component onto the Panel Accordion.
  23. Change the Text property to Second Steps .
  24. In the Layout section of the Component Palette, select the Panel List component to insert it into the Show Detail Item.
  25. In the Common section of the Component Palette, select the Output Text component three times to insert 3 instances into the Panel List.
  26. Add Step 4: Make something cool , Step 5: Get everyone to buy it , Step 6: Prosper!! for the Value property of each Output Text component, respectively.
  27. Save the file.

Create three task flows and associated page fragments to use as single instance dynamic tabs

To create the first taskflow and associated fragment:

  1. Open a context menu on uiShellViewController.
  2. Select New.
  3. In the New Gallery under Web Tier, select the JSF category.
  4. On the right hand side, select the ADF Task Flow.
  5. In the Create Task Flow dialog, type first.xml for the task flow name.
  6. The Directory field should default to: C:\JDeveloper\mywork\UIShell\uiShellViewController\public_html\WEB-INF\flows

    If not, use the Browse button to select WEB-INF > flows.

  7. Click OK.
  8. Drag and drop a view activity onto the task flow diagram.
  9. Change the name to one .
  10. Open the one view activity (e.g., double-click).
  11. This should result in the Create New JSF Page Fragment dialog.

    The Directory field should default to: C:\JDeveloper\mywork\UIShell\uiShellViewController\public_html\fragments

    If not, use the Browse button to select fragments.

  12. Click OK to accept defaults.
  13. In the Layout section of the Component Palette, select the Panel Group Layout component to insert it into the page fragment
  14. From the Layout section of the Component Palette, drag and drop the Panel Accordion component onto the the Panel Group Layout.
  15. Select the showDetailItem component nested within the Panel Accordion in the Structure Window
  16. Change the Text property to First Steps .
  17. In the Layout section of the Component Palette, select the Panel List component to insert it into the Show Detail Item.
  18. In the Common section of the Component Palette, select the Output Text component three times to insert 3 instances into the Panel List.
  19. Add Step 1: Do something , Step 2: And then something else , Step 3: Be happy! for the Value property of each Output Text component, respectively.
  20. From the Common section of the Component Palette, drag and drop the Show Detail Item component onto the Panel Accordion.
  21. Change the Text property to Second Steps .
  22. In the Layout section of the Component Palette, select the Panel List component to insert it into the Show Detail Item.
  23. In the Common section of the Component Palette, select the Output Text component three times to insert 3 instances into the Panel List.
  24. Add Step 4: Make something cool , Step 5: Get everyone to buy it , Step 6: Prosper!! for the Value property of each Output Text component, respectively.
  25. Save the file.

To create the second taskflow and associated fragment:

  1. Open a context menu on uiShellViewController\ public_html\WEB-INF\flows.
  2. Select New.
  3. In the New Gallery under Web Tier, select the JSF category.
  4. On the right hand side, select the ADF Task Flow.
  5. In the Create Task Flow dialog, type second.xml for the task flow name.
  6. Click OK.
  7. Drag and drop a view activity onto the task flow diagram.
  8. Change the name to two .
  9. Open the two view activity (e.g., double-click).
  10. This should result in the Create New JSF Page Fragment dialog.

    The Directory field should default to: C:\JDeveloper\mywork\UIShell\uiShellViewController\public_html\fragments

    If not, use the Browse button to select fragments.

  11. Click OK to accept defaults.
  12. In the Layout section of the Component Palette, select the Panel Group Layout component to insert it into the page fragment
  13. In the Common section of the Property Inspector, change the Layout to vertical .
  14. In the Common section of the Component Palette, select the Output Text component to insert it into the the Panel Group Layout.
  15. In the Common section of the Property Inspector, type The second activity! for the Value property.
  16. In the Style section of the Property Inspector, type the following for InlineStyle: color:Orange; font-size:x-large; font-weight:bold;
  17. In the Layout section of the Component Palette, drag and drop the Spacer component onto the the Panel Group Layout.
  18. In the Common section of the Component Palette, drag and drop the Button component onto the the Panel Group Layout.
  19. In the Common section of the Property Inspector, type Third Activity in the Text property.
  20. Save the file.

To create the third taskflow and associated fragment:

  1. Open a context menu on uiShellViewController\ public_html\WEB-INF\flows.
  2. Select New.
  3. In the New Gallery under Web Tier, select the JSF category.
  4. On the right hand side, select the ADF Task Flow.
  5. In the Create Task Flow dialog, type third.xml for the task flow name.
  6. Click OK.
  7. Drag and drop a view activity onto the task flow diagram.
  8. Change the name to three .
  9. Open the three view activity (e.g., double-click).
  10. This should result in the Create New JSF Page Fragment dialog.

    The Directory field should default to: C:\JDeveloper\mywork\UIShell\uiShellViewController\public_html\fragments

    If not, use the Browse button to select WEB-INF > fragments.

  11. Click OK to accept defaults.
  12. In the Layout section of the Component Palette, select the Panel Group Layout component to insert it into the page fragment
  13. In the Common section of the Property Inspector, change the Layout to vertical .
  14. In the Common section of the Component Palette, select the Output Text component to insert it into the the Panel Group Layout.
  15. In the Common section of the Property Inspector, type The third activity! for the Value property.
  16. In the Style section of the Property Inspector, type the following for InlineStyle: color:Blue; font-size:x-large; font-weight:bold;
  17. In the Layout section of the Component Palette, drag and drop the Spacer component onto the the Panel Group Layout.
  18. In the Common section of the Component Palette, drag and drop the Button component onto the the Panel Group Layout.
  19. In the Common section of the Property Inspector, type Finish This Activity in the Text property.
  20. Save the application.

Create Managed Bean

Note: Access to the APIs within TabContext are available only after a page within the application workspace has been added based on the Oracle Dynamic Tabs Shell template. Pages based on the Oracle Dynamic Tabs Shell template were created earlier.

To create a managed bean whereby the TabContext APIs can be called more conveniently:

  1. Open the context menu on uiShellViewController.
  2. Select New.
  3. In the New Gallery under Java, select Java Class.
  4. Click OK.
  5. In the Create Java Class dialog, type Launcher for Class Name.
  6. Type src.view for the Package name or other appropriate package name.
  7. Both Constructors from Superclass and Implement Abstract Methods can be unchecked.
  8. Click OK.
  9. Add or copy the following into the Launcher.java file and save the file.


 /* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */
package src.view;

import javax.faces.event.ActionEvent;

import oracle.ui.pattern.dynamicShell.TabContext;

/**
 * Launcher is a backingBean-scope managed bean. The public methods are
 * available to EL. The methods call TabContext APIs available to the
 * Dynamic Tab Shell Template. The boolean value for _launchActivity
 * determines whether another tab instance is created or selected. Each tab
 * (i.e., task flow) is tracked by ID. The title is the tab label.
 */

public class Launcher
{
  public void multipleInstanceActivity(ActionEvent actionEvent)
  {
    /**
    * Example method when called repeatedly, will open another instance as
    * oppose to selecting a previously opened tab instance. Note the boolean
    * to create another tab instance is set to true.
    */
     
    _launchActivity(
      "A New Activity",
      "/WEB-INF/flows/new.xml#new",
      true);
  }
 
  public void launchFirstActivity(ActionEvent actionEvent)
  {
      /**
      * Example method to call a single instance task flow. Note the boolean
      * to create another tab instance is set to false. The taskflow ID is used
      * to track whether to create a new tab or select an existing one.
      */
    _launchActivity(
      "The First Activity",
      "/WEB-INF/flows/first.xml#first",
      false);
  }
 
  public void launchSecondActivity(ActionEvent actionEvent)
  {
    _launchActivity(
      "Next Activity",
      "/WEB-INF/flows/second.xml#second",
      false);
  }
 
  public void launchThirdActivity(ActionEvent actionEvent)
  {
    _launchActivity(
      "Third Activity",
      "/WEB-INF/flows/third.xml#third",
      false);
  }
 
  public void closeCurrentActivity(ActionEvent actionEvent)
  {
    TabContext tabContext = TabContext.getCurrentInstance();
    int tabIndex = tabContext.getSelectedTabIndex();
    if (tabIndex != -1)
    {
      tabContext.removeTab(tabIndex);
    }
  }
 
    public void currentTabDirty(ActionEvent e)
    {
        /**
        * When called, marks the current tab "dirty". Only at the View level
        * is it possible to mark a tab dirty since the model level does not
        * track to which tab data belongs.
        */
      TabContext tabContext = TabContext.getCurrentInstance();
      tabContext.markCurrentTabDirty(true);
    } 
 
    public void currentTabClean(ActionEvent e)
    {
      TabContext tabContext = TabContext.getCurrentInstance();
      tabContext.markCurrentTabDirty(false);
    }
      
  private void _launchActivity(String title, String taskflowId, boolean newTab)
  {
    try
    {
      if (newTab)
      {
        TabContext.getCurrentInstance().addTab(
          title,
          taskflowId);
      }
      else
      {
        TabContext.getCurrentInstance().addOrSelectTab(
          title,
          taskflowId);
      }
    }
    catch (TabContext.TabOverflowException toe)
    {
      // causes a dialog to be displayed to the user saying that there are
      // too many tabs open - the new tab will not be opened...
      toe.handleDefault(); 
    }
  }

    public void launchFirstReplaceNPlace(ActionEvent actionEvent)
    {
      TabContext tabContext = TabContext.getCurrentInstance();
      try
      {
        tabContext.setMainContent("/WEB-INF/flows/first.xml#first");
      }
      catch (TabContext.TabContentAreaDirtyException toe)
      {
          // TODO: warn user TabContext api needed for this use case.
      }
    }

    public void launchSecondReplaceNPlace(ActionEvent actionEvent)
    {
      TabContext tabContext = TabContext.getCurrentInstance();
      try
      {
        tabContext.setMainContent("/WEB-INF/flows/second.xml#second");
      }
      catch (TabContext.TabContentAreaDirtyException toe)
      {
          // TODO: warn user TabContext api needed for this use case.         
      }
    }
}

 

A reference to the managed bean should be added to the adfc-config.xml file. This will allow the pages to pass control to the methods called within Launcher to realize the dynamic tab behavior.

To accomplish this:

  1. In the Editor pane of the IDE, select the tab for the adfc-config.xml file.
  2. At the bottom of the Editor pane of the IDE, select the tab for the Overview editor.
  3. Among the finger tabs to the left, select Managed Beans.
  4. In the upper right hand corner, select the Add icon (i.e., green plus symbol).
  5. In the table type launcher for the Name.
  6. In the next column, type src.view.Launcher for the Class.
  7. In the next column, select backingBean for the Scope.
  8. Save the file.

Call Task Flows as Dynamic Tabs from Managed Bean

The methods within Launcher are accessible via EL. Each page will demonstrate a different method within Launcher.

To call three taskflows, each as a dynamic tab via a managed bean in the navigation pane in the first page:

  1. In the Editor pane of the IDE, select the tab for the First.jspx file.
  2. In the Structure Window, select the navigation facet.

    For demonstration purposes, components comprising a UI will be nested within the navigation facet. However, it would be better practice to create a navigation taskflow. This would allow, for example, the convenience of adding it as a dynamic region to this facet. The result could be different navigation options based on the role or responsibility of the authenticated user -- each dynamic region containing a different navigation taskflow.

  3. In the Layout section of the Component Palette, select the Decorative Box component to insert it into the navigation facet.

    The Decroative Box adds rounded corners to its children. It also supports changing of the rendered theme of its children. In other words, it can act as a L&F transition between areas on a page. In this case, it distinguishes the Navigation Area from the Local Content Area.

  4. In the Layout section of the Component Palette, select the Panel Group Layout component to insert it into the center facet of the Decorative Box.
  5. In the Common section of the Property Inspector, change the Layout property to vertical .
  6. In the Common section of the Component Palette, select the Output Text component to insert it into the the Panel Group Layout.
  7. In the Common section of the Property Inspector, type Choose your activity for the Value property.
  8. In the Style section of the Property Inspector, type the following for InlineStyle: font-size:large; font-weight:bold;
  9. From the Layout section of the Component Palette, drag and drop the Panel List component onto the the Panel Group Layout.
  10. In the Common section of the Component Palette, drag and drop the Link component three times onto the Panel List.
  11. In the Structure Window, select the first Link component.
  12. In the Common section of the Property Inspector, type Start First Activity for the Text property.
  13. Select the Property Menu for the ActionListener property.
  14. Select Edit from the Property Menu.
  15. In the Edit Property: ActionListener dialog, select launcher in the Managed Bean drop down.
  16. In the Edit Property: ActionListener dialog, select launchFirstActivity in the Method drop down.
  17. Click OK.

    The Edit Property: ActionListener dialog will insert the following expression (EL): #{backingBeanScope.launcher.launchFirstActivity} . Similar EL will be inserted with each use of the dialog for the Managed Bean: launcher .

  18. In the Behavior section of the Property Inspector, change the PartialSubmit property to true .
  19. In the Structure Window, select the second Link component.
  20. In the Common section of the Property Inspector, type Start Next Thing for the Text property.
  21. Select the Property Menu for the ActionListener property.
  22. Select Edit from the Property Menu.
  23. In the Edit Property: ActionListener dialog, select launcher in the Managed Bean drop down.
  24. In the Edit Property: ActionListener dialog, select launchSecondActivity in the Method drop down.
  25. Click OK.
  26. In the Behavior section of the Property Inspector, change the PartialSubmit property to true .
  27. In the Structure Window, select the third Link component.
  28. In the Common section of the Property Inspector, type Execute Third Task for the Text property.
  29. Select the Property Menu for the ActionListener property.
  30. Select Edit from the Property Menu.
  31. In the Edit Property: ActionListener dialog, select launcher in the Managed Bean drop down.
  32. In the Edit Property: ActionListener dialog, select launchThirdActivity in the Method drop down.
  33. Click OK.
  34. In the Behavior section of the Property Inspector, change the PartialSubmit property to true .
  35. Save the file.

The Second page will demonstrate closing a taskflow from the toolbar, as well as, marking a tab dirty then clean.

To call three taskflows, each as a dynamic tab via a managed bean in the navigation toolbar in the second page:

  1. In the Editor pane of the IDE, select the tab for the Second.jspx file.
  2. In the Structure Window, select the innerToolbar facet.
  3. In the Layout section of the Component Palette, select the Panel Group Layout component to insert it into the innerToolbar facet.
  4. In the Common section of the Property Inspector, change the Layout property to vertical .
  5. In the Layout section of the Component Palette, select the Toolbox component to insert it into the the Panel Group Layout.
  6. In the Operations section of the Component Palette, select the Group component to insert it into the Toolbox component.

    The Group component is necessary here to align both a menubar components and toolbar components horizontally in the same toolbar.

  7. In the Common section of the Component Palette, select the Panel Menu Bar component to insert it into the Group component.
  8. In the Common section of the Component Palette, select the Menu component to insert it into the Panel Menu Bar component.
  9. In the Common section of the Property Inspector, change the Text property to Action .
  10. In the Common section of the Component Palette, select the Menu Item component to insert it into the Menu component.
  11. In the Common section of the Property Inspector, change the Text property to New .
  12. Select the Property Menu for the ActionListener property.
  13. Select Edit from the Property Menu.
  14. In the Edit Property: ActionListener dialog, select launcher in the Managed Bean drop down.
  15. In the Edit Property: ActionListener dialog, select multipleInstanceActivity in the Method drop down.
  16. Click OK.
  17. From the Common section of the Component Palette, drag and drop a Menu Item component to insert it into the Menu component.
  18. In the Common section of the Property Inspector, type Next Activity for the Text property.
  19. Select the Property Menu for the ActionListener property.
  20. Select Edit from the Property Menu.
  21. In the Edit Property: ActionListener dialog, select launcher in the Managed Bean drop down.
  22. In the Edit Property: ActionListener dialog, select launchSecondActivity in the Method drop down.
  23. Click OK.
  24. From the Common section of the Component Palette, drag and drop another Menu Item component to insert it into the Menu component.
  25. In the Common section of the Property Inspector, type Final Task for the Text property.
  26. Select the Property Menu for the ActionListener property.
  27. Select Edit from the Property Menu.
  28. In the Edit Property: ActionListener dialog, select launcher in the Managed Bean drop down.
  29. In the Edit Property: ActionListener dialog, select launchThirdActivity in the Method drop down.
  30. Click OK.
  31. From the Common section of the Component Palette, drag and drop the last Menu Item component to insert it into the Menu component.
  32. In the Common section of the Property Inspector, change the Text property to Close .
  33. Select the Property Menu for the ActionListener property.
  34. Select Edit from the Property Menu.
  35. In the Edit Property: ActionListener dialog, select launcher in the Managed Bean drop down.
  36. In the Edit Property: ActionListener dialog, select closeCurrentActivity in the Method drop down.
  37. Click OK.
  38. In the Behavior section of the Property Inspector, Select the Property Menu for the Disabled property.
  39. Select Expression Builder from the Property Menu.
  40. In the Expression Builder dialog, add the following to the Expression text box: #{viewScope.tabContext.selectedTabIndex < 0} .

    The viewScope object tabContext.selectedTabIndex is made available via the TabContext class. All available scope objects can be inspected via the Expression Builder ADF Managed Beans tree node on any page based on the UI Shell template. When the tabContext.selectedTabIndex is less than zero (i.e., no dynamic tabs are open) the Close menu option is disabled.

Optionally, textual toolbar buttons, iconic toolbar buttons (if appropriate icons are available), or additional menu items (except for the first toolbar button) could be added.

The following steps assume icons are available for the enabled, disabled, mouseover, and mousedown states.

  1. From the Common section of the Component Palette, drag and drop the Toolbar component onto the Group component.
  2. In the Common section of the Component Palette, select the Toolbar Button component three times to insert them into the Toolbar component.
  3. Select the first toolbar button.
  4. Select the Property Menu for the Text property.
  5. Select Reset to Default from the Property Menu to remove the text label.
  6. Iconic toolbar buttons are assumed. Here a "New" icon New icon would be appropriate.
  7. Select the Property Menu for the ActionListener property.
  8. Select Edit from the Property Menu.
  9. In the Edit Property: ActionListener dialog, select launcher in the Managed Bean drop down.
  10. In the Edit Property: ActionListener dialog, select multipleInstanceActivity in the Method drop down.
  11. Click OK.
  12. In the Appearance section of the Property Inspector, add the path to the appropriate enabled, mouseover, mousedown and disabled icons for the Icon, HoverIcon, DepressedIcon, and DisabledIcon properties.
  13. Select the second toolbar button.
  14. Select the Property Menu for the Text property.
  15. Select Reset to Default from the Property Menu to remove the text label.
  16. Iconic toolbar buttons are assumed. Here an "Edit" icon Edit icon might be appropriate.
  17. Select the Property Menu for the ActionListener property.
  18. Select Edit from the Property Menu.
  19. In the Edit Property: ActionListener dialog, select launcher in the Managed Bean drop down.
  20. In the Edit Property: ActionListener dialog, select currentTabDirty in the Method drop down.

    A more appropriate UI approach might be to set the tab dirty with a method call from a value change listener on input component(s) within the taskflow.

  21. Click OK.
  22. In the Appearance section of the Property Inspector, select the Property Menu for the Rendered property.
  23. Select Expression Builder from the Property Menu.
  24. In the Expression Builder dialog, add the following to the Expression text box: #{viewScope.tabContext.selectedTabIndex >= 0} .

    When the tabContext.selectedTabIndex is greater than or equal zero (i.e., dynamic tabs are open) this property is true and the icon is rendered. Conversely, the Disabled property in the Behavior section of the Property Inspector could have been used with the appropriate EL to simply disable the icon when no dynamic tabs were opened. Both behaviors are good UI for toolbars depending on the larger context and UI goals. In either case, the same method (i.e., rendered, disabled) should be used for functions that are highly correlated.

  25. In the Appearance section of the Property Inspector, add the path to the appropriate enabled, mouseover, mousedown and disabled icons for the Icon, HoverIcon, DepressedIcon, and DisabledIcon properties.
  26. Select the third toolbar button.
  27. Select the Property Menu for the Text property.
  28. Select Reset to Default from the Property Menu to remove the text label.
  29. Iconic toolbar buttons are assumed. Here an "Task Completed" icon Task Completed icon might be appropriate.
  30. Select the Property Menu for the ActionListener property.
  31. Select Edit from the Property Menu.
  32. In the Edit Property: ActionListener dialog, select launcher in the Managed Bean drop down.
  33. In the Edit Property: ActionListener dialog, select currentTabClean in the Method drop down.

    A more appropriate UI approach might be to set the tab clean with a method call from button (e.g., submit, save) within the taskflow.

  34. Click OK.
  35. In the Appearance section of the Property Inspector, select the Property Menu for the Rendered property.
  36. Select Expression Builder from the Property Menu.
  37. In the Expression Builder dialog, add the following to the Expression text box: #{viewScope.tabContext.selectedTabIndex >= 0} .

    When the tabContext.selectedTabIndex is greater than or equal zero (i.e., dynamic tabs are open) this property is true and the icon is rendered. Conversely, the Disabled property in the Behavior section of the Property Inspector could have been used with the appropriate EL to simply disable the icon when the no dynamic tabs were opened. Both behaviors are good UI for toolbars depending on the larger context and UI goals. In either case, the same method (i.e., rendered, disabled) should be used for functions that are highly correlated.

  38. In the Appearance section of the Property Inspector, add the path to the appropriate enabled, mouseover, mousedown and disabled icons for the Icon, HoverIcon, DepressedIcon, and DisabledIcon properties.
  39. From the Layout section of the Component Palette, drag and drop the Spacer component onto the the Panel Group Layout.
  40. Save the file.

Note: Since a replace-in-place method cannot be called from a page that has dynamic tabs open (not only would it throw an exception, it is a poor UI method), the Third Page will be used.

To call three taskflows, each as a Replace-in-Place UI via a managed bean in the navigation toolbar in the third page:

  1. In the Editor pane of the IDE, select the tab for the Third.jspx file.
  2. In the Structure Window, select the innerToolbar facet.
  3. In the Layout section of the Component Palette, select the Panel Group Layout component to insert it into the innerToolbar facet.
  4. In the Common section of the Property Inspector, change the Layout property to vertical .
  5. In the Layout section of the Component Palette, select the Toolbox component to insert it into the the Panel Group Layout
  6. In the Common section of the Component Palette, select the Panel Menu Bar component to insert it into the Toolbox component.
  7. In the Common section of the Component Palette, select the Menu component to insert it into the Panel Menu Bar component.
  8. In the Common section of the Property Inspector, change the Text property to Action .
  9. In the Common section of the Component Palette, select the Menu Item component three times to insert them into the Menu component.
  10. Select the first Menu Item component.
  11. In the Common section of the Property Inspector, type First Activity for the Text property.
  12. Select the Property Menu for the ActionListener property.
  13. Select Edit from the Property Menu.
  14. In the Edit Property: ActionListener dialog, select launcher in the Managed Bean drop down.
  15. In the Edit Property: ActionListener dialog, select launchFirstReplaceNPlace in the Method drop down.
  16. Click OK.
  17. Select the second Menu Item component.
  18. In the Common section of the Property Inspector, type Second Activity for the Text property.
  19. Select the Property Menu for the ActionListener property.
  20. Select Edit from the Property Menu.
  21. In the Edit Property: ActionListener dialog, select launcher in the Managed Bean drop down.
  22. In the Edit Property: ActionListener dialog, select launchSecondReplaceNPlace in the Method drop down.

    The taskflow called has within it a button when activated launches a separate taskflow. If the current taskflow is in a clean state, that subsequent taskflow will be called as a replace-in-place taskflow whether that call uses the TabContext.setMainContent or the TabContext.getCurrentInstance API. When the subsequent taskflow has a return or is closed, the calling taskflow is rendered. If the current taskflow is dirty, the call to the subsequent taskflow fails silently. This is a known issue.

  23. Click OK.
  24. Select the third Menu Item component.
  25. In the Common section of the Property Inspector, change the Text property to Close.
  26. Select the Property Menu for the ActionListener property.
  27. Select Edit from the Property Menu.
  28. In the Edit Property: ActionListener dialog, select launcher in the Managed Bean drop down.
  29. In the Edit Property: ActionListener dialog, select closeCurrentActivity in the Method drop down.
  30. Click OK.
  31. In the Behavior section of the Property Inspector, Select the Property Menu for the Disabled property.
  32. Select Expression Builder from the Property Menu.
  33. In the Expression Builder dialog, add the following to the Expression text box: #{viewScope.tabContext.selectedTabIndex < 0} .
  34. Click OK.
  35. Save the application.

Note: If the calling taskflow is open when the called taskflow is closed, selection returns to the calling taskflow when the replace-in-place method is used. When the dynamic tab method is used, the selection returns to the first called task flow.

To call a taskflow as a dynamic tab from another taskflow via a managed bean:

  1. In the Editor pane of the IDE, select the tab for the second.xml taskflow.
  2. At the bottom of the Editor pane of the IDE, select the tab for the Overview editor.
  3. Among the finger tabs to the left, select Parameters.
  4. In the upper right hand corner, select the Add icon (i.e., green plus symbol) above the Input Parameter Definitions table.
  5. In the table type tabContext for the Name.
  6. In the next column, type oracle.ui.pattern.dynamicShell.TabContex for the Class.
  7. In the next column accept the default.
  8. In the next column, enable Required (i.e., set value to true).

    Adding the input paramter allows access to TabContext methods from within a task flow.

  9. Save the file.
  10. In the Editor pane of the IDE, select the tab for the two.jsff page fragment.
  11. In the Visual Editor select the button labeled Third Activity .
  12. Select the Property Menu for the ActionListener property.
  13. Select Edit from the Property Menu.
  14. In the Edit Property: ActionListener dialog, select launcher in the Managed Bean drop down.
  15. In the Edit Property: ActionListener dialog, select launchThirdActivity in the Method drop down.
  16. Click OK.
  17. Save the file.

To call a taskflow as a Replace-in-Place UI from another taskflow via a managed bean:

Call taskflow three from within taskflow two with the TabContext.setMainContent API from within the Third.jspx page. Because taskflow two will not "close" when taskflow three is called, navigation is transferred back to taskflow two when taskflow three is eventually closed.

Note: If a taskflow is in a dirty state, the UI Shell template as with other close methods (e.g., Close icon, Close menu item) will automatically raise an unsaved data warning dialog to the user.

To close a taskflow from within, prior to completion via a managed bean:

  1. In the Editor pane of the IDE, select the tab for the third.xml taskflow.
  2. At the bottom of the Editor pane of the IDE, select the tab for the Overview editor.
  3. Among the finger tabs to the left, select Parameters.
  4. In the upper right hand corner, select the Add icon (i.e., green plus symbol) above the Input Parameter Definitions table.
  5. In the table type tabContext for the Name.
  6. In the next column, type oracle.ui.pattern.dynamicShell.TabContex for the Class.
  7. In the next column, enable Required (i.e., set value to true).

    Adding the input paramter allows access to TabContext methods from within a task flow.

  8. Save the file.
  9. In the Editor pane of the IDE, select the tab for the three.jsff page fragment.
  10. In the Visual Editor select the button labeled Finish This Activity .
  11. Select the Property Menu for the ActionListener property.
  12. Select Edit from the Property Menu.
  13. In the Edit Property: ActionListener dialog, select launcher in the Managed Bean drop down.
  14. In the Edit Property: ActionListener dialog, select closeCurrentActivity in the Method drop down.
  15. Click OK.
  16. Save the file.
Adding Welcome Page Content

An optional "Welcome Page" can be added to each page of the demo. It is advisable to add content to the welcome facet of each page based on the UI Shell template.

Create an Optional Welcome taskflow

The following steps will describe adding Welcome content to First.jspx only:

  1. Open a context menu on uiShellViewController.
  2. Select New
  3. In the New Gallery under Web Tier, select the JSF category.
  4. On the right hand side, select the ADF Task Flow.
  5. In the Create Task Flow dialog, type welcome.xml for the task flow File Name.
  6. In the Directory field, append the path to read: C:\JDeveloper\mywork\UIShell\uiShellViewController\public_html\WEB-INF\flows

    This is a convenience to improve the workspace organization.

  7. Click OK.
  8. Drag and drop a view activity onto the task flow diagram.
  9. Change the name to you .
  10. Open the you view activity (e.g., double-click).

    This should result in the Create New JSF Page Fragment dialog. In the Directory field, append the path to read:
    C:\JDeveloper\mywork\UIShell\uiShellViewController\public_html\fragments . This is a convenience to improve the workspace organization.

  11. Click OK to accept defaults.
  12. In the Layout section of the Component Palette, select the the Panel Group Layout component to insert it into the page fragment.
  13. In the Common section of the Property Inspector, change the Halign property of the Panel Group Layout to center .
  14. In the Common section of the Property Inspector, change the Layout property to vertical .
  15. In the Common section of the Component Palette, select the Output Text component to insert it into the the Panel Group Layout.
  16. In the Common section of the Property Inspector, type Welcome to Our Application! in the Value field.
  17. In the Style Section of the Property Inspector, add the following to the InlineStyle property: color:Blue; font-size:x-large; font-weight:bold;
  18. In the Layout section of the Component Palette, drag and drop the Spacer component into the the Panel Group Layout.
  19. In the Common section of the Property Inspector, change the height property to 30 .
  20. Add appropriate images or text.
  21. Save the application.
  22. In the Editor pane of the IDE, select the tab for the First.jspx file.
  23. From the Application Navigator, drag and drop the Welcome taskflow into the Welcome facet of First.jspx.
  24. In the Create popup, select Region.

    The Welcome page should appear within First.jspx.

  25. Save the file.

Run Application

At this point, run the demonstration application from any of the jspx pages (i.e., First, Second, Third) to see the various behaviors of the UI Shell.

Instead of completing these step, an ADF application on OTN called UIShell is available at https://www.oracle.com/docs/tech/developer-tools/uishellapp.zip. It can be unzipped into the designated work area and opened with JDeveloper. Simply download UIShell.zip; unzip the archive; and open the UIShell.jws with JDeveloper. This pattern has been tested against JDeveloper Studio 12c (12.1.2.0.0).

Use Case Example for Using the Dynamic Tab Shell Template Source Directly

As stated in Pattern Implementation, when a page is based on the Oracle Dynamic Tab Shell template, the template and its associated ADF artifacts and Java classes are added to the JDeveloper workspace (i.e., the ADF application) by reference. There are use cases where it is more convenient to include these ADF artifacts and Java classes into a workspace (i.e., *.jws) directly. For example, the content for the facets (e.g., global links, legal notices) for a series of pages based on the template may all be identical. Instead of copying that content over and over to each created page based on the template, it may be more efficient to add that content once to the dynamicTabShell.jspx (i.e., the template file) and then deploy that workspace as an ADF library for reuse. The modified template is available to team members with those modifications in place. The Oracle Dynamic Tab Shell template source is available as a JDeveloper workspace on OTN within an archive at https://www.oracle.com/technetwork/developer-tools/adf/dynamic-tab-shell-src-121200.zip.

Support for Multi Browser Tabs

As separate to the dynamic tab feature provided by the ADF UI Shell, contemporary browsers give the user the ability to open multiple tabs within the browser. Each browser tab can view different URLs allowing the user to browse different websites simultaneously, or even the same website multiple times.

While the implementation of this is browser specific, currently all contemporary browsers including Apple's Safari, Google's Chrome, Microsoft's Internet Explorer and Mozilla Firefox do not maintain separate network sessions to websites for each browser tab. Rather if a user is visiting the same website multiple times across browser tabs, the same user session will be used.

From the server side Oracle's ADF does provide the ability to support multi browser tabs sharing the same session though it is left up to the ADF programmer to decide if they wish their application to support this through the correct use of pageFlowScope beans. While it does seem desirable to support this be default, allowing the user to surf your application multiple times simultaneously can impact the load on your system so you need to consider your options.

In considering the ADF UI Shell's options it does not support multi browser tabs by default. To enable this you must add the context parameter USE_PAGEFLOW_TAB_TRACKING equal to true in your web.xml.

To enable multi browser tab support for the ADF UI Shell in your application:

  1. Open the ViewController project in the Application Navigator.
  2. Under the Web Content folder expand the WEB-INF folder, then double click the web.xml file.
  3. With the web.xml file editor open, select the Overview tab at the bottom of the editor if not selected, and ensure the Application node is open on the left menu of the editor.
  4. Expand the Context Initialization Parameters accordion control.
  5. Select the plus Create Context Initialization Parameter button.
  6. In the name column enter USE_PAGEFFLOW_TAB_TRACKING and true for the value column.
  7. Save your changes.

Known Issues

There is a known issues with the Oracle Dynamic Shell Template. The unsaved data warning dialog unavailable with tabcontext.setmaincontent.

Related Topics

https://www.oracle.com/application-development/technologies/adf/unsaveddatawarning.html