Chapter 5. Navigation and Layout

An often overlooked area of application design is how users will navigate around the system. We typically give a lot of thought to how individual screens and pages will look; but, we don't always give the same amount of consideration to how the user will move among those pages. Why is this important? Well, if users find it difficult to navigate your application, they will quickly become frustrated with the application. Your application should have a navigation system that's easy to use and takes into account the areas users will access most frequently

APEX provides many components and methods that enable you to create different ways for users to navigate applications. However, there's no magic formula for determining which method or component will be most suitable for your particular situation—that's something you'll need to decide on a case-by-case basis.

This chapter covers some of the different tools Apex puts at your disposal for enabling navigation in your application. We'll concentrate here on using the built-in themes and templates. In Chapter 10, you'll see how you can modify these—and even create your own themes—to customize your application's look and feel, as well as its navigation system.

It is worth noting that in APEX 4.0, there are even more available themes and new features that can improve the user experience. We'll explore some of those features in this chapter.

Tabs

Tabs are an extremely simple yet efficient way of allowing users to navigate between different pages in your application. They are perhaps among the first navigation aids developers might choose to include, since APEX makes it extremely easy to implement them.

You can use two different types of tabs: standard and parent. Standard tabs are for applications that have only one level of tabs, with each tab associated with a particular page (although a tab can also be the current tab for many pages, as you'll see shortly). A parent tab, in contrast, acts as a container for a group of standard tabs. Using parent tabs, you can group standard tabs under a particular parent tab in order to define a more contextual list of tabs that is specific to the user's current task.

You can access the tabs used in your application in many different ways. For example, each page definition in the Application Builder contains a list of the tabs used on that page in the Shared Components section, as shown in Figure 5-1.

Tabs displayed in the Shared Components for the page definition

Figure 5.1. Tabs displayed in the Shared Components for the page definition

You can also view all of your application's tabs from the Shared Components section for the application, as shown in Figure 5-2. This screen is actually very comprehensive. It not only shows the tabs you've defined for the application, but also displays information about the definition of each individual tab.

Tabs displayed in the Shared Components for the application

Figure 5.2. Tabs displayed in the Shared Components for the application

Understanding Tab States: Current and Noncurrent

In the example in Figure 5-2, notice that the tab has a single target, represented by the Tab Current for Page attribute—page 1 in this case. In other words, when the users click the tab, they will be taken to page 1. However, the tab can also be "current" for a number of pages, represented by the Tab Also Current for Pages attribute. In Figure 5-2, the tab is considered current for pages 2 through 5. So what does current actually mean?

A tab has two states: either current or noncurrent. The difference between current and noncurrent is quite a fluid one, in that you can customize your templates to have your own definitions, as you'll learn in Chapter 10. However, generally speaking, for the built-in themes and templates, a current tab reflects the fact that the user is currently on a page represented by that tab. In other words, the tab will appear to be different from the other tabs and, again generally, the tab will not be a clickable link. A noncurrent tab reflects the fact that the user can click the tab to navigate to a different page. Current tabs may use different images or colors so users can see at a glance where they are in the application. Exactly how the current and noncurrent states are implemented depends on the way the page template used for the page implements the standard tabs.

When users click a tab, they are taken to the page that's assigned as the current page for that tab (page 1 in the example), and the tab is considered the current tab. However, if the user is on one of the pages 2 through 5, the tab will also be considered the current one.

Using Standard Tabs

When an application uses a single level of tabs, they are standard tabs. The Buglist application has a standard tab set called TS1, as shown in Figure 5-3, which was created automatically when you created the application. All of the standard tabs belong to this tab set.

The standard tab set in the Buglist application

Figure 5.3. The standard tab set in the Buglist application

Figure 5-3 shows the definition of one of the tabs for the Buglist application. Here, you can define a single page for the page that will be linked to from this tab, as well as multiple entries in the Tab Also Current for Pages attribute, by specifying the individual page numbers separated by commas. You can also place the tab in another tab set, if one exists, by changing the Standard Tab Set attribute.

The tab attributes include both Tab Name and Tab Label. The Tab Name attribute is the name you'll use to refer to the tab within your application. The Tab Label attribute is the text that will appear on the tab when displayed to the user (if you customize the templates, you can display anything you like). You can actually do quite a few interesting things with the Tab Label attribute. The text doesn't need to be static and hard-coded. You can use substitution values in the Tab Label attribute, which will be replaced dynamically at runtime. For example, rather than setting the Tab Label attribute to Edit Bug, you could use Edit Bug &BUG_NUMBER., which at runtime would show something like "Edit Bug 174," allowing users to see at a glance which bug they are editing.

Figure 5-4 shows some of the other attributes you can define for a particular standard tab. You can specify images to be used for the current and noncurrent states, as well as any additional image attributes. You can also link the tab to a parent tab set and define an authorization scheme for the tab.

Attributes of a standard tab

Figure 5.4. Attributes of a standard tab

The Buglist application uses a page template called One Level Tabs. Figure 5-5 shows the definition of the Standard Tabs Attributes section of this template. We'll cover the details of page templates in Chapter 10; however, from Figure 5-5, you can see that the HTML used for current and noncurrent standard tabs is slightly different—the tabs use different images and different CSS classes for the Tab Label attribute. In this particular page template, the images used for the current and noncurrent tabs are hard-coded. However, if the template for your application uses the #TAB_IMAGE# substitution variable, then the values you entered for the image attributes shown in Figure 5-4 would be applied instead.

Page template definition for the standard tab attributes

Figure 5.5. Page template definition for the standard tab attributes

By using authorization schemes with standard tabs, you can control whether a user can access a particular page through a tab. For example, if you implement the business requirement that only administrators should be able to access the Analyze page of your application, you can change the authorization scheme of the Analyze tab to use the USER_IS_ADMIN scheme you created earlier (in Chapter 4), as shown in Figure 5-6.

Using an authorization scheme with a standard tab

Figure 5.6. Using an authorization scheme with a standard tab

Now if you run the application while logged in as an administrator, you will see the Analyze tab, as shown in Figure 5-7. However, if you are logged in as a nonadministrator, you will not see that tab, as shown in Figure 5-8.

An administrator sees both tabs.

Figure 5.7. An administrator sees both tabs.

The Analyze tab is not displayed to nonadministrators.

Figure 5.8. The Analyze tab is not displayed to nonadministrators.

Note

You might have expected to see an error displayed when the nonadministrator logged in, as shown in Figure 5-8. However, in this case, rather than the authorization scheme displaying an error, the tab is simply not displayed to anyone failing the authorization scheme logic, which is preferable behavior for navigation components such as tabs.

As you can see, using authorization schemes with standard tabs is an incredibly powerful way of customizing the navigation of your application dynamically at runtime depending on who is logged in (or any other criteria you prefer).

It is also possible to use conditions to determine whether a standard tab should be displayed, which gives even more flexibility to dynamically customize the navigation at runtime. We'll discuss how to define conditions for navigation in the "Navigation Bars" section later in this chapter.

Using Parent Tabs

In order to use parent tabs, you need to use a page template that supports them. Since the Buglist application currently uses One Level Tabs as the page template, you can't use parent tabs in it. Fortunately, this is quite easy to change. Just edit the page definition and select a page template that supports two levels of tabs, Two Level Tabs, as shown in Figure 5-9.

Now if you run the page again, it will look similar to Figure 5-10. Since you haven't defined a parent tab yet, the tab display is still much like it was before (aesthetics aside).

Note

If you used a different theme, you might see something very different from Figure 5-10, since each theme can display the tab layout in different ways. In fact, themes don't actually have to support displaying two levels of tabs.

Changing the Report page to use the Two Level Tabs template

Figure 5.9. Changing the Report page to use the Two Level Tabs template

The page using the Two Level Tabs page template

Figure 5.10. The page using the Two Level Tabs page template

As an example, let's create a new parent tab set called Bugtools, under which you'll group all of the bug-related standard tabs. To begin, click the Add link beside the TS1 tab set, as shown back in Figure 5-2. The link reads "Add," but if you hover your mouse over the link, the pop-up hint reads "Add New Parent Tab." This starts the parent tab creation wizard, as shown in Figure 5-11.

Note

As with most APEX components, there are many different ways to reach the creation wizard for parent tabs, such as through the page definition or through the Shared Components section for the application. Look around the Application Builder to find all the different ways you can do tasks like this. You'll probably have a favorite way of doing these things, but it's always good to be able to find different routes since they might end up saving you more time (and make you more productive!).

Creating a parent tab

Figure 5.11. Creating a parent tab

Give the parent tab a label and then assign a target page. You can also assign other attributes that will affect the session state when the user uses the tab, as shown in Figure 5-12.

Adding parent tab attributes

Figure 5.12. Adding parent tab attributes

The attributes you can assign to parent tabs are similar to the usual settings you can make for page branches. You can specify a Request value, which can then be used within processes on the page to determine how the user arrived at that page. You can also clear session state from particular pages and assign values to items held in the session state. For now, simply make the tab take the user to page 1 and don't do anything with the session state. As you can see from Figure 5-13, the new parent tab you created has now replaced the TS1 tab set.

Now suppose you create a new page that displays some helpful information about the application. One of the options during page creation is to define whether a tab or parent tab should be reused or created for that particular page.

Figures 5-14 and 5-15 show how parent tabs can help to present different navigation choices to your users depending on which top-level parent tab they select. One tab shows a bug list; the other shows application help.

A new parent tab replaces the old TS1 tab set.

Figure 5.13. A new parent tab replaces the old TS1 tab set.

The Bugtools tab shows a list of tracked bugs.

Figure 5.14. The Bugtools tab shows a list of tracked bugs.

The Help tab shows online help.

Figure 5.15. The Help tab shows online help.

At first, getting parent tabs and two-level tabs working in your application can be quite confusing. Many people find that after they create parent tabs they are unable to get them to display in their application. This is usually because they don't understand how tab sets, parent tabs, and page templates work. If you are having problems getting your parent tabs to display, check whether you are using the correct parent tab set for that particular standard tab and also whether you have made the tab current for that page.

I find it very helpful to open two pages, one running the application and another running the APEX development environment. You can then make changes to the tabs or pages, then switch over to the running application and simply refresh the page to get the new code and test the functionality. Multi-tab browsers, like FireFox and IE8 make this really easy.

Note

We encourage you to sit down and work through creating some parent tabs. Once you get the hang of this, it really isn't difficult, although it can seem that way when it is not working how you intended.

Navigation Bars

Like tabs, navigation bars can be an easy way to enable user navigation in your application. Unlike with tabs, though, an application may use only a single navigation bar. However, that navigation bar can contain multiple entries that are dynamically enabled and disabled at runtime.

If you look at the page template, you'll see #NAVIGATION_BAR# specified in the Body section (again, this depends on whether the page template and theme you are using support displaying a navigation bar). At runtime, the #NAVIGATION_BAR# is substituted for the actual HTML that represents the individual navigation bar entries.

Accessing Navigation Bar Entries

You can access the current navigation bar entries either through the Shared Components section of the application, as shown in Figure 5-16, or through the Navigation Bar section in the page definition.

Accessing navigation bar entries

Figure 5.16. Accessing navigation bar entries

The Buglist application currently has only a single navigation bar entry defined. This is the Logout entry, which produces the Logout link shown in the top-right corner of the page. Figure 5-17 shows the attributes for this Logout entry. As you can see, you can define an image and a target for the entry. In this case, the entry is using the special URL target of &LOGOUT_URL., which you can define within the authentication scheme for the application. For this application, the following target will be substituted:

wwv_flow_custom_auth_std.logout?p_this_flow=&APP_ID.&p_next_flow_page_sess=
&APP_ID.:1
Attributes for the Logout navigation bar entry

Figure 5.17. Attributes for the Logout navigation bar entry

This means that when the user clicks the Logout link, the standard wwv_flow_custom_auth_std.logout routine will be called, which performs some standard logout logic that you can use in your own applications. The parameters to the URL (which are used as parameters to the procedure) mean that users will be returned to page 1 in the application once they have successfully reauthenticated (remember that page 1 requires authentication).

Again, as with tabs, you can also use conditions with navigation bar entries, as shown in Figure 5-18. This example specifies that the navigation bar entry should be displayed only if the user is on page 1 or page 5.

The conditions for the Logout navigation bar entry

Figure 5.18. The conditions for the Logout navigation bar entry

Although navigation bar entries don't have the same capabilities as tabs in terms of being able to define current and noncurrent pages, you can use conditions to effectively mimic the same sort of behavior. For example, you can use the current page number or some other criteria to display different navigation bar entries.

Creating Navigation Bar Entries

Let's create a couple of new navigation bar entries: a simple Home entry to take users back to the first page of the application and a Help entry to open a pop-up Help window. Notice that when you create a navigation bar entry from scratch, you are asked whether this will navigate to a standard URL or to a Feedback page. As described in Chapter 1, Feedback pages are used to gather comments from users. For this exercise, we will use the URL method.

Create the Home entry as shown in Figure 5-19. To keep the example simple, just use a text link. However, you could quite easily use an image as well as or instead of the text. Add a simple condition, as shown in Figure 5-20, saying that the entry will not be displayed if users are already on the home page. Also, rather than using a URL target type, use a page in the application as the target, as shown in Figure 5-21.

Creating the Home navigation bar entry

Figure 5.19. Creating the Home navigation bar entry

Using a condition with the Home navigation bar entry

Figure 5.20. Using a condition with the Home navigation bar entry

Specifying the page target for the Home navigation bar entry

Figure 5.21. Specifying the page target for the Home navigation bar entry

If you run the page again, you'll see the new navigation bar entry displayed in the top-right corner, alongside the Logout link, as shown in Figure 5-22 (but remember that you won't see the new entry if you are already on page 1). Notice that the new Home link appears before the Logout link. That's because the Sequence attribute for the Home link is a numeric value that's less than the Sequence attribute value for the Logout link. The navigation bar entries are output in ascending order, so you can use the Sequence attribute to maintain a particular order among your entries.

The new Home navigation bar entry is displayed next to the Logout link.

Figure 5.22. The new Home navigation bar entry is displayed next to the Logout link.

Now let's create the Help entry. This time, use a URL target, as shown in Figure 5-23. The URL target uses the following value:

javascript:popUp2('f?p=&APP_ID.:HELP:&SESSION.', 400, 400);

The popUp2 JavaScript routine is one that is defined in the standard APEX JavaScript libraries, so you can use it in your own applications. The first parameter to the procedure is the URL you wish to open. Here, you're passing in the standard APEX URL f?p as well as some parameters to it that will take you to the Help page in the same application (note that here you're using the page alias HELP, rather than passing in a numeric page ID). The second and third parameters to the JavaScript routine are the width and the height of the pop-up window.

Creating the Help navigation bar entry

Figure 5.23. Creating the Help navigation bar entry

If you now rerun the page and click the Help link, you should see something similar to Figure 5-24. Note that the pop-up window is actually displaying the Help page as it would appear if you had navigated to it using the tabs; that is, you now have a pop-up window that also contains tabs and navigation bar entries. In a production application, most likely you wouldn't want to do this. Instead, you could define a very minimal page template specifically for your pop-up windows and use that. However, this example does demonstrate that you can easily add the ability to create a pop-up window from your navigation bar.

Displaying the pop-up Help window

Figure 5.24. Displaying the pop-up Help window

Performing an Action on the Current Page

In some cases, you might want your navigation bar entry to take you back to perform an action on the current page. For example, you might want an entry to print the current page, to make the current page printer-friendly, or to reset the pagination on the current page. In this case, rather than hard-coding the page ID, you can use the substitution variable &APP_PAGE_ID., which will be replaced by the current page ID when you run the application. This way, the same navigation bar entry is able to work on multiple pages.

Figure 5-25 shows how to use &APP_PAGE_ID. to create a navigation bar entry that will put each page into Printer Friendly mode. Here, the page target specified is the &APP_PAGE_ID. substitution variable, and the Printer Friendly check box is selected. If you now run the application and click the Printer Friendly navigation bar entry, you will see a screen similar to Figure 5-26.

Note

Make sure you add the period "." after the name of the &APP_PAGE_ID or you will get a nasty browser error that does not identify the root cause of the problem. You will not be able to see the entire substitution variable in the properties panel.

Using the &APP_PAGE_ID. substitution variable to put the page in Printer Friendly mode

Figure 5.25. Using the &APP_PAGE_ID. substitution variable to put the page in Printer Friendly mode

A page in Printer Friendly mode

Figure 5.26. A page in Printer Friendly mode

Note that there is no magic behind Printer Friendly mode. All it does is to make the page use a specific page template in which you can alter the layout of the page to be more suitable for printing. In this example, the template removed the navigation bars as well as the tabs and some of the form fields. You can completely customize the Printer Friendly template if you wish.

Tip

Navigation bars may not suit all types of applications, but they do offer a very simple and quick way of defining a navigation system for your application. You may want to use navigation bars during the prototype phase of your application, while you're toying with different ideas for screen layouts.

Breadcrumbs

Breadcrumbs are yet another tool you can use to help users navigate your application. However, unlike most of the other navigation tools, breadcrumbs have a quite unique characteristic: they allow users to easily see their current position in the application relative to other areas of the application. Users can go back to previous locations in the application by following the breadcrumb trail created by their actions.

The Buglist application already has a breadcrumb menu, displayed just below the tabs, as shown in Figure 5-27. In this figure, the breadcrumb trail says the user is currently on the Analyze page and got to that page via the home page. Actually, the last part of the preceding sentence may or may not be true, since breadcrumbs allow for a great deal of flexibility in how you associate breadcrumb entries with each other. The way to read the breadcrumb trail in this case is that the user is able to go directly to the home page by clicking the Home link in the breadcrumb trail.

The breadcrumb trail shows the user is on the Analyze page.

Figure 5.27. The breadcrumb trail shows the user is on the Analyze page.

An application can have multiple breadcrumbs defined and can display multiple breadcrumbs simultaneously. However, we suggest you use only one breadcrumb menu, perhaps two if necessary. Displaying more than two menus is rarely helpful and can actually make the task of navigating more confusing.

Accessing Breadcrumb Entries

You can view the breadcrumbs for your application from the Shared Components section, as shown in Figure 5-28, or via the page definition. If you select the Buglist breadcrumb, you also get a very useful outline of the breadcrumb entries, as shown in Figure 5-29.

Breadcrumb defined for the application

Figure 5.28. Breadcrumb defined for the application

Breadcrumb entries defined for the Buglist breadcrumb

Figure 5.29. Breadcrumb entries defined for the Buglist breadcrumb

This outline view of the breadcrumb entries makes it easy to see how each breadcrumb entry relates to every other breadcrumb. For example, you can see that the root entry is Home, with four entries below it: Analyze, Insert Bug, Update Bug, and Success. The Analyze entry also contains a number of entries below it. You can also see that each breadcrumb entry corresponds to a particular page. This is similar to the way that tabs can be tied to a particular page; however, unlike a tab, a breadcrumb can relate to only an individual page.

Figure 5-30 shows some of the interesting attributes you can define for a breadcrumb entry:

Page:

Specifies where the breadcrumb entry will appear. You can see that the Analyze breadcrumb entry is assigned to page 5, which means that the breadcrumb entry will be shown if you are on page 5.

Short Name and Long Name:

Specifying a short name for the breadcrumb entry is mandatory. Optionally, you can also enter a long name. Depending on the theme and page template you use, the breadcrumb menu might use either the short name or the long name.

Parent Entry:

Defines the parent breadcrumb entry that will appear with this breadcrumb entry. The parent for the Analyze breadcrumb is the Home breadcrumb, so if you are on page 5, you will see not only the Analyze breadcrumb, but also the Home breadcrumb. Similarly, if you have any other breadcrumbs that use the Analyze breadcrumb as their parent, the Analyze breadcrumb will also be displayed when you are on any of those pages. As mentioned earlier, the Home breadcrumb entry is the root entry, because it doesn't have a parent entry defined. There can be only one root breadcrumb entry in your breadcrumb trail.

Target:

Assigns a target for the breadcrumb entry. In this case, the target is also page 5, so clicking the breadcrumb entry will take you to page 5. (Remember that the breadcrumb entry can also be displayed when the user is on a page other than page 5 if that page uses a breadcrumb that is a descendant of this breadcrumb.) You can also choose a page target different from the page used in the Breadcrumb section. Bear in mind that this may be confusing to users, since the page they branched to would not be the same as the page the breadcrumb links to; however, there may be cases where this is the behavior you want.

Breadcrumb entry attributes

Figure 5.30. Breadcrumb entry attributes

Using Dynamic Breadcrumb Entries

As with some of the other navigation tools, you can use substitution variables with breadcrumb entries to enable them to display dynamic information at runtime. For example, if you want to modify the Update Bug breadcrumb entry to also display the number of the bug that is currently being edited, you could include the substitution variable P3_ID in the Short Name attribute for the breadcrumb, since this is the page item that represents the ID of the current bug, as shown in Figure 5-31. Then, when you edit a bug, the breadcrumb entry will also contain the bug ID, as shown in Figure 5-32.

This is a bit of a contrived example, since the bug ID might not be that useful in the breadcrumb entry. However, sometimes including dynamic information in the breadcrumb entry is a good idea. For example, imagine you are drilling down into a report of employees belonging to different departments. Once you select a department, you could filter the list of employees to show only those belonging to that particular department. You could show the department in the breadcrumb entry, so that users can easily see which department they are currently viewing.

Note

Using substitution variables is not just limited to breadcrumb entries. You can use this technique in many different places to make your user interface much more dynamic and reflect at runtime what your users are actually doing.

Using a substitution variable in the breadcrumb entry

Figure 5.31. Using a substitution variable in the breadcrumb entry

The breadcrumb entry now displays the bug ID.

Figure 5.32. The breadcrumb entry now displays the bug ID.

Displaying Breadcrumbs

To display your breadcrumb menu on a page, you must create a Breadcrumb region on that page, as shown in Figure 5-33. You can then select which breadcrumb menu you wish to use, as shown in Figure 5-34. The wizard allows you to create a new breadcrumb entry for the page and specify which breadcrumb entry should be the parent for the new entry, as shown in Figure 5-35. Figure 5-36 shows the page running after the new breadcrumb has been added.

Adding a Breadcrumb region to the Help page

Figure 5.33. Adding a Breadcrumb region to the Help page

Selecting the breadcrumb to use in the region

Figure 5.34. Selecting the breadcrumb to use in the region

Defining the parent breadcrumb entry

Figure 5.35. Defining the parent breadcrumb entry

New Breadcrumb region displayed on the page

Figure 5.36. New Breadcrumb region displayed on the page

You might be thinking that having to create a Breadcrumb region on each page is quite repetitive work and surely there must be an easier way to do it. You're absolutely right. An easier way to do it is by using page zero. As mentioned in Chapter 1, page zero is useful for displaying the same page element on all or multiple pages of your application; it's discussed in more detail later in this chapter.

Lists

Lists are another tool you can use to create a navigation aid in your application. Lists share many of the features of tabs, navigation bars, and breadcrumbs. They are extremely versatile—perhaps even more so than some of the other navigation tools.

Lists offer simplicity and ease of use, and you can use them to create many different types of navigation interfaces—with amazing results. Some great user interfaces are created using nothing more than some CSS and a list (for example, the APEX Evangelists site at http://apex-evangelists.com and the DG Tournament site at /www.dgtournament.com), so don't underestimate them. In fact, some developers opt to use a list where others would choose tabs.

Accessing List Entries

The Buglist application already contains a couple of lists, created automatically by the application creation wizard. The lists are visible on the Analyze page, as shown in Figure 5-37. One list shows the links for the reports, and the other displays the links available for charts. At first glance, the lists don't appear particularly exciting. In fact, they look like links, similar to the navigation bar entries.

Lists as a navigation aid

Figure 5.37. Lists as a navigation aid

The Lists section of the Shared Components shows the two lists that were created, as shown in Figure 5-38. If you examine the Charts list, you can see the individual list items, as shown in Figure 5-39.

The list entries look similar to the entries you can have in standard tabs or the navigation bar. You can give each list entry a target (where clicking the list entry will take the user), as well as define a condition for each. It's only when you view the individual attributes for a list entry that you can see the full range of available settings, as shown in Figures 5-40 and 5-41.

Lists available as shared components for the application

Figure 5.38. Lists available as shared components for the application

List entries in the Charts list

Figure 5.39. List entries in the Charts list

List entry attributes

Figure 5.40. List entry attributes

More list entry attributes

Figure 5.41. More list entry attributes

In a way, lists combine the simplicity of navigation bar entries with the complexity of tabs. You can see from Figure 5-40 that you can build a hierarchy of list entries, with one entry being the parent of another. You can also define a target page for the list entry, as well as define the list of pages for which this list entry should be regarded as current, in much the same way as with tabs.

Currently, none of the Charts list entries has a parent defined, which is why they all appear at the same level in the list. You can easily change the parent entry for some of the entries, as shown in Figure 5-42. Here, the By Reported list entry is the parent of the By Status and By Report By list entries. However, if you ran the application again, you would not see any difference in the way the list entries are displayed on screen. This is because the template that is currently being used for the list does not take the hierarchy into account.

List with an implied hierarchy

Figure 5.42. List with an implied hierarchy

To show the hierarchy, you need to change the template from Vertical Unordered List without Bullet to another template, such as DHTML Tree, as shown in Figure 5-43. Now if you run the page, you should see the output shown in Figure 5-44. In this figure, we've expanded the list by clicking the plus sign (+) next to By Reported, which reveals the two items under it.

Changing the list template

Figure 5.43. Changing the list template

The list is now displayed in a hierarchical manner.

Figure 5.44. The list is now displayed in a hierarchical manner.

You can use other built-in templates to change the appearance of the list. By simply changing the template, you can change the list from being a vertical list to a horizontal list. You can also define images used with each list entry, or you could go for a completely DHTML menu. In fact, with APEX, you can have total control over the look of the list, since you can define your own list template. That way, you can create pretty much any sort of layout that is possible with HTML, CSS, and JavaScript.

Creating a Menu Using a List

So, how can you create a menu for your application using a list? You can do this by using the same principles as the two lists that were automatically created: add a new list and then create new list entries that link to particular pages. You can then display that list on each page, which will enable users to navigate to different pages.

Figure 5-45 shows the first step of creating a new list, using the Vertical Sidebar List template. (You can always change the list template later.) Next, create some simple list entry items for the list, as shown in Figure 5-46. These entries have been linked to the same pages you'd be able to navigate to using the tabs or links in the application.

Creating a new list to use as a menu

Figure 5.45. Creating a new list to use as a menu

Adding list entries

Figure 5.46. Adding list entries

Now you need to display the list on the page, so create a new region on the home page as shown in Figure 5-47. This example uses the Sidebar Region for the template and also positions the display point of the region on the right side of the screen. The template for this region has been changed to Tree List (note that the template used for the region and the template used for the list are different types). If you now run the application and look at the home page, you'll see the list menu, as shown in Figure 5-48.

Note

You'd probably expect a navigation menu to appear on the left side of the screen (well, people who read from left to right would expect that). However, in the page template used in this example, there is no suitable position on the left side. As you'll see in Chapter 10, you can modify the page template to position items wherever you desire.

Creating a new list region on the home page

Figure 5.47. Creating a new list region on the home page

Displaying the navigation list

Figure 5.48. Displaying the navigation list

Clicking a list entry will take you to the relevant page. However, the menu is displayed only on the home page at the moment; if you click a link that takes you to another page, you won't be able to access the navigation list from there. As with breadcrumbs, you need to create a region on each individual page to display the list. And again, you can use page zero to achieve that in an efficient way.

As with tabs, you can also incorporate authorization schemes with individual list entries. For example, if you want to make sure that only administrators can access the Assigned To list entry, select the USER_IS_ADMIN authorization scheme you created in Chapter 4, as shown in Figure 5-49. If you now log in as a nonadministrator (using the jimb user, for example) and access the home page, you will no longer see the Assigned To list entry, as shown in Figure 5-50.

Adding an authorization scheme to a list item

Figure 5.49. Adding an authorization scheme to a list item

Nonadministrators will not see the Assigned To entry.

Figure 5.50. Nonadministrators will not see the Assigned To entry.

Notice that the hierarchy of the list items is still preserved, even though one of the items is no longer visible. You might be wondering what would happen if you applied the same authorization scheme check to the Analyze entry. As you can see in Figure 5-51, in that case, not only is the Analysis entry not visible, but you also can't see any entries that have the Analysis entry as their parent (and so on down the hierarchy chain).

Child entries are also hidden by authorization schemes.

Figure 5.51. Child entries are also hidden by authorization schemes.

So, even though you haven't applied the authorization check to the Reported By list entry, the fact that you applied the authorization check to the parent item means that unauthorized users can't see any children of that parent item. This is an extremely powerful way of controlling access to a hierarchy.

Tracking Clicks on List Entries

Lists have a couple of features that can be extremely useful in certain circumstances. One is the ability to automatically count the number of times a user selects a particular list entry.

Through the attributes of each individual list entry, you can specify whether clicks on that entry should be counted, as well as a category for that click. By using categories, you can group different list entries for statistical purposes. For example, rather than counting individual clicks to both the By Reported By and By Assigned To entries, you might group both entries into an Analysis category. You might also enable the Home list entry for click counting and assign it a category of Home, as shown in Figure 5-52.

Counting list entry clicks

Figure 5.52. Counting list entry clicks

The clicks are counted internally through the APEX_UTIL.COUNT_CLICK procedure (or the shorthand notation Z), which will automatically log the clicks so you can view the results in the Administration section of your workspace. In the example in Figure 5-53, you can see that user jimb clicked two list items, both in the Home category (actually, he clicked the Home entry twice).

Note

The click log isn't very detailed. For example, you can't see where the user was connecting from (his remote IP address) or what type of web browser he used. However, for simple logging purposes, the click log is definitely worth using.

Viewing external clicks in the Workspace Administration section

Figure 5.53. Viewing external clicks in the Workspace Administration section

You can use this functionality when you want to keep a simple record of how your users navigate through your system. It can be very useful to know which areas of your application are the least or most used. Based on this information, you may want to adapt your application's design so that the most commonly used parts of the application are easy to access.

Using User-Defined Attributes for List Entries

So, what other tricks can you do with lists? The answer lies in the rather vaguely named User Defined Attributes section of the list entry, as shown in Figure 5-54.

The first three of the ten user-defined attributes you can add to a list item

Figure 5.54. The first three of the ten user-defined attributes you can add to a list item

What are these attributes for? As the name implies, they're for anything you would like. The key is understanding how the list template works. For example, the definition for the Tree List template shows that the same HTML is used to represent the list items, regardless of whether they are considered current, as shown in Figure 5-55.

Suppose you want to change the way each entry is displayed by wrapping each one in an HTML DIV section and using some CSS to specify what each DIV section should look like. The problem here is that using the standard attributes, you can differentiate between only a current and noncurrent entry, not between the different entries themselves. However, by using the user-defined attributes, you can change the look of individual entries. First, modify the HTML in the Template Definition section to wrap the entry in a DIV section:

<div id="#A01#"><li><a href="#LINK#">#TEXT#</a></li></div>

The substitution variable #A01# corresponds to the first user-defined attribute. Similarly, #A02# corresponds to the second user-defined attribute, #A03# to the third, and so on.

Definition of the Tree List template

Figure 5.55. Definition of the Tree List template

Next, specify a value for the first user-defined attribute for the Home list entry, as shown in Figure 5-56.

Specifying a user-defined attribute

Figure 5.56. Specifying a user-defined attribute

If you now run the application and view the HTML source code for the home page (you can usually do this via the View menu in your browser or by right-clicking the page and choosing View Source), you should see that the HTML generated for the Home list entry looks like this (with the code between the anchor tags omitted for brevity):

<div id="HOMEDIV"><li><a ...></a></li></div>

You can see that the DIV ID contains the substitution value that was specified in the User Defined Attributes section for the Home entry. Now you can implement your own CSS and then style each list entry in whatever way you desired.

Trees

Trees are typically used where you wish to represent hierarchical information. As you saw in the previous sections, you can create a menu system with a hierarchy, so you should be able to use a tree to display it.

So how would you go about creating a menu framework using a tree? As an example, let's mimic the menu created earlier using lists, this time using a table to specify the entries.

Creating a Table for the Tree Entries

First, create a simple table to hold the list of entries, as shown in Listing 5-1.

Example 5-1. Creating a Table to Store the Tree Entries

apexdemo@DBTEST> create table tree_navigation(

  2  id number,
  3  parent_id number,
  4  title varchar2(30),
  5  link varchar2(60));

Table created.

The table is very simple, containing only four columns:

  • The id column will contain a unique identifier for the entry.

  • The parent_id column will refer to the ID of another entry if this entry has a parent. If parent_id is null, that entry will be considered to be the root node for the tree. There can be only a single root node.

  • The title column will be the text displayed in the tree.

  • The link column will enable you to direct users to another location if they click a particular tree node.

Next, insert some records that will mimic the same hierarchy used with the list earlier, as shown in Listing 5-2.

Example 5-2. Creating Data for the Tree Layout

apexdemo@DBTEST> insert into tree_navigation

  2  values
  3  (1, null, 'Home', 'f?p=&APP_ID.:1:&SESSION.'),

1 row created.

apexdemo@DBTEST> insert into tree_navigation
  2  values
  3  (2, 1, 'Analysis', 'f?p=&APP_ID.:5:&SESSION.'),

1 row created.

apexdemo@DBTEST> insert into tree_navigation
  2  values
  3  (3, 2, 'Assigned To', 'f?p=&APP_ID.:13:&SESSION.'),

1 row created.

apexdemo@DBTEST> insert into tree_navigation
  2  values
  3  (4, 2, 'Reported By', 'f?p=&APP_ID.:10:&SESSION.'),

1 row created.

apexdemo@DBTEST> commit;

Commit complete.

apexdemo@DBTEST> select * from tree_navigation;

 ID  PARENT_ID TITLE         LIN
--- ---------- ------------- ------------------------------
  1            Home          f?p=&APP_ID.:1:&SESSION.
  2          1 Analysis      f?p=&APP_ID.:5:&SESSION.
  3          2 Assigned To   f?p=&APP_ID.:13:&SESSION.
  4          2 Reported By   f?p=&APP_ID.:10:&SESSION.

Notice that the records use a link in the format of f?p, which allows you to refer to another page in the application. The benefit of doing it this way is that you can also specify links external to the application by using a fully qualified URL, such as http://www.google.com.

Note

This is a simple example for demonstration purposes. In practice, you'd probably want to use a sequence for the ID column, rather than manually inserting a value. Also, you'd need to ensure that there was only one entry in the table with a parent_id of null; that is, only one root node should be allowed. And, of course, in your production system, you would want to investigate some suitable indexes for a table like this!

Creating the Tree Component

Now you can create the tree component, as shown in Figure 5-57. By default, the tree creation wizard will create the tree on a new page. If you wish to place the tree on an existing page, change the Page Number attribute to the page you wish to use.

Creating a tree

Figure 5.57. Creating a tree

APEX 4.0 lets you choose from three basic tree templates as shown in Figure 5-58. Choose the Classic style for this example.

Selecting the tree template

Figure 5.58. Selecting the tree template

You can choose to base the root node of your tree on a pop-up LOV, a SQL query, or a static item. Since this example stores the root node in the same table as the rest of the tree entries, choose to base it on a SQL query, as shown in Figure 5-59. The query for the root node is very simple:

select id from tree_navigation where parent_id is null

You could use some other criteria in your own applications, such as always giving the root node an ID of zero. However, in this example, the root node will have a null parent_id, so this simple query will work.

The wizard will then ask which schema and table should be used to create the tree. You will also need to specify which columns in that table to use, as shown in Figure 5-59. Also, as shown in the figure, choose to make the leaf node text a link by setting the Link Option attribute to Existing Application Item. This allows you to use the link column in the table.

Selecting the tree attributes

Figure 5.59. Selecting the tree attributes

If you now run the application, you should see a new Tree region on the page, as shown in Figure 5-60. If users click any of the tree entries, they will be taken to the page specified in the link column of the table.

Tree region being driven from the table

Figure 5.60. Tree region being driven from the table

Enabling and Disabling Tree Entries

You can extend this example to add the ability to enable and disable tree entries. As shown in Listing 5-3, add an enabled column to the table and update the Assigned To entry to be disabled.

Example 5-3. Adding an Enabled Column to the Table

apexdemo@DBTEST> alter table tree_navigation

  2  add (enabled char(1) default 'Y'),

Table altered.

apexdemo@DBTEST> update tree_navigation
  2  set enabled = 'N' where id = 3;

1 row updated.

apexdemo@DBTEST> commit;

Commit complete.

apexdemo@DBTEST> select * from tree_navigation;

  ID  PARENT_ID TITLE         LINK                           ENABLE
--- ---------- ------------- ------------------------------ -------
  1            Home          f?p=&APP_ID.:1:&SESSION.       Y
  2          1 Analysis      f?p=&APP_ID.:5:&SESSION.       Y
  3          2 Assigned To   f?p=&APP_ID.:13:&SESSION.      N
  4          2 Reported By   f?p=&APP_ID.:10:&SESSION.      Y

Now modify the tree query to use the new enabled column, as shown in Listing 5-4.

Example 5-4. Adding a Restriction to the Tree Query

select "ID" id,

       "PARENT_ID" pid,
       "TITLE" name,
       "LINK" link,
       null a1,
       null a2
from "#OWNER#"."TREE_NAVIGATION"

If you run the application again, you will see that the Assigned To entry is no longer displayed in the tree, as shown in Figure 5-61. As with a list menu, if you disable an entry that also contains child nodes (for example, the Analysis entry), the child nodes will also be disabled. That means you won't see any child nodes that descend from the disabled node, even if those child nodes are not disabled themselves.

Disabled entries do not appear in the tree.

Figure 5.61. Disabled entries do not appear in the tree.

Tip

For another example of what you can do with trees, see Tony Jedlinski's excellent article "Build a Menu Framework." This article was published in the May/June 2006 edition of Oracle Magazine and is also available online (currently at www.oracle.com/technetwork/issue-archive/2006/06-may/o36apex-086847.html).

Page Zero

How does page zero relate to navigation? As you've learned in this chapter, breadcrumbs and lists (and trees, too) need to be created in a region on each page you wish to use them. Page zero is the solution to all that repetitive work.

You can think of page zero as a page with a very special purpose: to define elements that can appear on multiple pages within your application. In other words, if you define a region on page zero, that region can automatically appear on page 10 or page 15, even though you didn't specifically define the region on those pages. The previous sentence says "can appear" rather than "will appear," because you have complete control (through the use of conditional logic) over which pages anything you define on page zero will affect.

As an example, let's use page zero to make the navigation list you created earlier appear on every page, rather than just the home page.

Creating Page Zero

The first step is to create a page zero, since it isn't automatically created for you in your application. The page creation wizard includes a Page Zero option, as shown in Figure 5-62.

The Page Zero option appears at the bottom of the page creation wizard's choices for page type.

Figure 5.62. The Page Zero option appears at the bottom of the page creation wizard's choices for page type.

Once the wizard has completed, you should see your new page zero, as shown in Figure 5-63. As you can see, in the Application Builder, page zero looks quite different from other pages. Also, notice that it is not possible to run page zero directly.

Page zero added to an application

Figure 5.63. Page zero added to an application

Adding Regions to Page Zero

You can now create a new List region on page zero, as you did earlier for the home page, and use it for the navigation list you created in the previous section. If you run the application again, you'll see that the home page now contains two list menus, as shown in Figure 5-64.

A List region defined on page zero appears on the Home page.

Figure 5.64. A List region defined on page zero appears on the Home page.

One of the lists is due to the region defined on page zero, and the other list is due to the region defined on the home page. If you click the Analysis link in either list, you will see that the list defined on page zero also appears on the Analysis page, as shown in Figure 5-65.

A List region defined on page zero shows on every page.

Figure 5.65. A List region defined on page zero shows on every page.

The benefits of using page zero should now be obvious. By defining a single region on page zero, you can display the same navigation menu on every page of your application. This means that you have drastically reduced the number of bits of code you need to maintain. For example, if you want to move the list from the right side of the screen to the left, you need do that in only a single place, on page zero. If you had defined the menu individually on each page, you would need to change it in every individual place. Centralizing the code makes it far easier to adapt your application, and it also removes the possibility of forgetting to make a change somewhere.

But what if you want the menu to appear on only certain pages, rather than on every page? Well, once again, that's incredibly easy to do. You just use a condition in the region on page zero. Figure 5-66 shows using the "Current Page Is Contained Within Expression 1 (comma delimited list of pages)" condition to specify the list of pages on which the region should be displayed.

Using a condition to specify certain pages

Figure 5.66. Using a condition to specify certain pages

Remember that you are limited only by your imagination here. You don't have to base the display on particular pages. Here are a few other possibilities:

  • The condition could check the value of an application item.

  • The condition could be based on the currently logged-in user.

  • The condition could check the current time (imagine a system that displays a certain menu only during "out-of-office-hours" time).

  • You could use some PL/SQL that queries a remote web server to determine if the menu should be shown.

Conditions allow amazing levels of control over your application. You can build some incredibly dynamic applications by using conditions within your navigational aids.

Layout

The built-in themes and templates allow you to position regions and page items in particular locations on the screen. Remember that you can create your own themes and templates, which allows you complete freedom to position your regions and items anywhere you desire. We will cover creating your own themes and templates in Chapter 10. Here, we'll concentrate on the mechanics of using the built-in ones.

Positioning Regions

Whenever you create a region on a page, you need to specify where you want the region to be positioned. In the Application Builder, you will see a drop-down list of all the currently available display points, as shown in Figure 5-67. These display points are defined in the current page template for the page.

List of currently available display points

Figure 5.67. List of currently available display points

If you look at the page template (accessed from the Templates section of the Page Definition page of the Application Builder or from the Shared Components section, which shows all the templates), you'll see a lot of HTML in different sections, which is used to generate the page at runtime. For example, the HTML for the Footer section of the Two Level Tabs page template is shown in Figure 5-68.

Notice the substitution variable called #REGION_POSITION_05#. This corresponds to the Page Template Region Position 5 option in the Display Point drop-down list. The HTML used for the Body section of the page template contains other substitution variables, which correspond to the other available display points. The positions of these substitution variables in the page template determine exactly where the display points that you use for your regions will appear at runtime.

Footer section for a page template

Figure 5.68. Footer section for a page template

Note that multiple regions can be contained in the same display point. In other words, you don't need to put each region into a different display point. The display point is effectively a container for your page regions, in the same way that the page itself is a container for different display points.

Fortunately, you don't need to keep checking the page template to see where each display point will end up being positioned. APEX makes it extremely easy to see how the display points will be displayed at runtime. Just click the small flashlight icon next to the Display Point drop-down list to see a pop-up window that shows a visual representation of the layout of the current page, as shown in Figure 5-69. For example, earlier in the chapter, you positioned the list menu in Region Position 3. From the pop-up layout window, you can see that Region Position 3 is on the right side of the screen.

Pop-up display of the page layout

Figure 5.69. Pop-up display of the page layout

This pop-up representation of the page layout is completely dynamic. If you change the page template to move the region positions around, the pop-up will reflect the changed positions.

The position of these regions is entirely dependent on the page template (and therefore dependent on the theme you are using). If you change the theme (or template) the application is using, you may find your page regions appear in different positions. This gives you an extremely powerful way of completely changing the look and feel of your application, without having to manually reposition the page regions. However, there may be cases where you are using a display point in one page template (for example, #REGION_POSITION_05#) that does not appear in another page template, since not all the region positions must be specified in a template. In this situation, you would need to choose another display point for your page region from the ones that are available in the new template.

Since you can have multiple page regions within the same display point, the order in which those page regions appear on the page is determined from the Sequence attribute value that you specified for each region, as shown in Figure 5-70.

Sequence attribute for a page region

Figure 5.70. Sequence attribute for a page region

The example shows a Sequence attribute of 40, which means that the region would be rendered after any regions that have a Sequence attribute lower than 40, but before any regions that have a Sequence attribute greater than 40. This makes it very easy to change the order of your regions within the display point simply by changing the Sequence attribute.

Also notice in Figure 5-70 the attribute named Column. This is used where you want to display multiple regions at the same horizontal position in the same display point. So, for example, if you modify the list that is defined on page 1 to use column 2 (remembering that the list defined on page zero is using column 1), you will see the two lists displayed horizontally next to each other, as shown in Figure 5-71.

Lists displayed in columns

Figure 5.71. Lists displayed in columns

To implement the Column attribute, behind the scenes, APEX creates an HTML table for your regions and uses the Column value to position the region within that particular column.

By using the Sequence and Column values, you can position multiple regions within the same display points in whatever vertical and/or horizontal arrangement you wish.

Positioning Page Items

Page items are positioned within page regions (buttons can be placed in a particular page region position or among the region items, for example), in much the same way that you position page regions within pages. Figure 5-72 shows the page items defined on the Update Bug screen.

Page items displayed in order of sequence

Figure 5.72. Page items displayed in order of sequence

In Figure 5-72, the sequence value of each item is displayed just to the left of the item name; for example, the P3_DESCRIPTION item has sequence 6. You can see that the page items use the sequence value to determine their order within the region.

You can also specify whether the page item should begin on a new line and field, as shown in Figure 5-73. The values that you select for these two attributes will determine how APEX displays the page item on the screen. Like the Column attribute for page regions, the Begin on New Line and Field attributes are used when APEX builds an HTML table to display the page items. If you select Yes for Begin on New Line, APEX will begin a new table row for your page item; otherwise, the item will be displayed horizontally after the previous page item. If you select Yes for the Field attribute, APEX will generate an HTML td tag (a new table column) in which to display your page item; otherwise, the page item will be displayed inside the same table column as the previous page item. Note that only certain combinations of Begin On New Line and Field are allowed: Yes/Yes, No/No, and No/Yes. You can't choose to begin on a new line without also creating a new field.

Display attributes for a page item

Figure 5.73. Display attributes for a page item

Drag-and-Drop Positioning

APEX 3.0 introduced drop-and-drop positioning for page items. This is a very slick and cool way to arrange your page items without needing to manually alter the sequence values and layout attributes.

To access the Drag and Drop Layout screen, click the small rectangular icon next to the up and down arrows in the Items section of your page. In Figure 5-72, you can see the icon just above the words "Number Field" to the right of P3_BUGID. A very useful feature is hiding behind this innocuous-looking icon.

Figure 5-74 shows the Drag and Drop Layout screen. All of the page items you have on your page will appear here. On this screen, you can drag the individual page items around and place them in new positions on the screen. You can also drag new page items onto the page and place them where you want them to appear. And you can remove page items by dragging and dropping them into the recycle bin at the bottom of the page.

Drag and Drop Layout screen (some page items omitted for brevity)

Figure 5.74. Drag and Drop Layout screen (some page items omitted for brevity)

This is a great new feature of APEX. It makes laying out your screen much easier, since you can see how it will look without having to run the application. Currently, drag-and-drop layout works on a per-region basis. A future release may extend this functionality to allow regions to be moved around using the same drag-and-drop method.

Summary

APEX supports several approaches to menus and layout. Tabs are commonly used on web pages, often to denote major sections within a site. APEX easily supports tabs. APEX also gives you the ability to create navigation bars for more detailed and granular navigation through a site. You can create navigation bar menus based on lists and trees that allow users to quickly navigate to specific pages. Breadcrumbs let you track a user's path through your site. Page zero and other layout-related features help you create and maintain a consistent look across all of your site's pages.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset