Skip to main content

Page 0 Branches

What? There's no way to put a Branch on Page 0 of an ApEx application! Or is there...

Technically, no - page 0 does not support branches. But how many times do you wish it did?

This scenario recently came up: I wanted to put a "Search" box on every page in my application, so no matter where a user is, they can search the site. Currently, it has 10 or so pages, but this will grow to closer to 50 by production.

So, thought #1 was to put an text item on Page 0, call it search, and then ensure that each and every page had some sort of Branch to run the search. Not so fun, as this was a tedious task, even for just 10 pages. And each time a new page was added to the application - by myself or anyone else - the search branch would have to be added to the page. Clearly not a scalable solution.

With a little bit of help from Raj from the ApEx team, I came up with this solution:
  • Create Page 0, if you haven't already
  • On page 0, create an item of type "Text Field (Always submits when enter pressed)" - this will let the user type in a search term and press return and fire off the search, as opposed to having to rely on a button being clicked
  • Create an Application Process (Shared Components > Application Processes)
  • Give it an unusually high Sequence number, such as 999999, as you want it to fire after ALL other page-level processes in your application
  • For the source, enter the following, making sure to use the page number that you want your search to branch to:
htp.init;
owa_util.redirect_url('f?p=&APP_ID.:710:&SESSION.');
htmldb_application.g_unrecoverable_error := true;

  • Put a condition on the Process to only fire when the REQUEST = P0_SEARCH, where P0_SEARCH is the name of your Search text item on Page 0
  • Run your application and test it out
Ideally, you will have some sort of Report on your Search page which is filtered by :P0_SEARCH, but you can really have that page do anything you want. You can also put more logic in the Application Process.

For example, I am using this method to first determine what level of access a user has. If they have Access Level A, then they branch to page 1; otherwise, they branch to page 10. Sure, I could accomplish this at the page level with two branches, but I need this functionality to be available application-wide. Thus, this solution saves me countless hours and some of my sanity.

Comments

Anonymous said…
Hi Scott,

I'm trying to understand your logic behind the very high sequence number. If a user using the search box, it usually means that he/she is not interesting in the page specific logic. As the search process is conditioned, I would expect it to receive a very low sequence number, so in case it is fired, it will be executed prior to any other page processes.

Also, what is the purpose of the htmldb_application.g_unrecoverable_error statement?

Thanks,
Arie.
Scott said…
I'm trying to understand your logic behind the very high sequence number. If a user using the search box, it usually means that he/she is not interesting in the page specific logic. As the search process is conditioned, I would expect it to receive a very low sequence number, so in case it is fired, it will be executed prior to any other page processes.

The reason that I recommend a high sequence number is that this Application Process should function as a branch. If you look at the order of operations when a page is submitted:

Validations > Computations > Processes > Branches

Putting it a high sequence number inserts it as close to the branch portion of the processing as possible.

Based on your needs, you can sequence it how you like, of course.

Also, what is the purpose of the htmldb_application.g_unrecoverable_error statement?

This stops all other HTML DB processing & branching. Thus, the owa_util.redirect_url procedure sucessfully fires, and any preceeding branch at the page level is ignored.

Thanks,

- Scott -
Anonymous said…
Hello Scott,

this is funny. Some half a year ago I implemented 99% the same solution in one of my application. The idea was, I can search on different numbers wherever I am - project number, order number, quote etc. It works as you described. The only difference I have is that:

1. the application process fires only if I enter a value to search upon,
2. only if the value matches a required content (numbers only, only numbers in a specific reange),
3. I didn't care about the sequence number
Anonymous said…
Hi Scott,

I can see your point now, but just to be sure I'm getting the whole picture, is it right to say that application processes will always be evaluated – and fire when necessary – prior to any other page processes, regardless of their higher sequence? (hence the use of the htmldb_application.g_unrecoverable_error statement?


Thanks a lot for your time, patient and the will to share,
Arie.
Scott said…
this is funny. Some half a year ago I implemented 99% the same solution in one of my application. The idea was, I can search on different numbers wherever I am - project number, order number, quote etc. It works as you described. The only difference I have is that:

Yes, you need to have a condition on the Process (REQUEST = Value works well). This way, you will only fire the process when a certain item is clicked/submitted.

- Scott -
Scott said…
I can see your point now, but just to be sure I'm getting the whole picture, is it right to say that application processes will always be evaluated – and fire when necessary – prior to any other page processes, regardless of their higher sequence? (hence the use of the htmldb_application.g_unrecoverable_error statement?

No - the way that I have it set up is that the Application Process will only fire when the REQUEST = Value, where the value is the name of the Search Box (P0_SEARCH in my case). It will, however, fire after all other page processes, as it has a high sequence number. Your needs may be different and require a lower sequence number - all depends on what you want to accomplish.

- Scott -
Anonymous said…
Not exactly related to branches but just Page 0.

I needed some Javascript functions available on almost all pages in my application. I created a Before Header HTML region with No Template and put the SCRIPT in there. Works like a charm!
Anonymous said…
Nice trick that I just used. Never would have thought of this one.
getyour411 said…
After several hours of Google breadcrumb trails and playing with page 0 // Dynamic Actions, I found your Blog post describing the very thing I wanted; thank you so much for posting this.

I see the post came from 2006, is this still the best way in Apex 4.x?
Scott said…
Believe it or not, it's still applicable today, as there is no such thing as a Page 0 Branch, even in APEX 4.0.

- Scott -
Anonymous said…
Scott,

But this doesn't work if you want to redirect to a page that's setup with No URL Access

I am trying to create a common process/branch to redirect to a page(with no url access) based on request.

Cheers
Scott said…
That's correct - No URL Access pages will prevent this solution from working.

When that option is selected, you will need to use a branch to get to that type of page, so off of the top of my head, I can't think of a global solution that would work for that. If I do, I'll post another comment here.

Thanks,

- Scott -
Anonymous said…
Only option I can think of is adding possibility of adding a branch on page 0. :)

Popular posts from this blog

Custom Export to CSV

It's been a while since I've updated my blog. I've been quite busy lately, and just have not had the time that I used to. We're expecting our 1st child in just a few short weeks now, so most of my free time has been spent learning Lamaze breathing, making the weekly run to Babies R Us, and relocating my office from the larger room upstairs to the smaller one downstairs - which I do happen to like MUCH more than I had anticipated. I have everything I need within a short walk - a bathroom, beer fridge, and 52" HD TV. I only need to go upstairs to eat and sleep now, but alas, this will all change soon... Recently, I was asked if you could change the way Export to CSV in ApEx works. The short answer is, of course, no. But it's not too difficult to "roll your own" CSV export procedure. Why would you want to do this? Well, the customer's requirement was to manipulate some data when the Export link was clicked, and then export it to CSV in a forma

Refreshing PL/SQL Regions in APEX

If you've been using APEX long enough, you've probably used a PL/SQL Region to render some sort of HTML that the APEX built-in components simply can't handle. Perhaps a complex chart or region that has a lot of custom content and/or layout. While best practices may be to use an APEX component, or if not, build a plugin, we all know that sometimes reality doesn't give us that kind of time or flexibility. While the PL/SQL Region is quite powerful, it still lacks a key feature: the ability to be refreshed by a Dynamic Action. This is true even in APEX 5. Fortunately, there's a simple workaround that only requires a small change to your code: change your procedure to a function and call it from a Classic Report region. In changing your procedure to a function, you'll likely only need to make one type of change: converting and htp.prn calls to instead populate and return a variable at the end of the function. Most, if not all of the rest of the code can rem

Logging APEX Report Downloads

A customer recently asked how APEX could track who clicked “download” from an Interactive Grid.  After some quick searching of the logs, I realized that APEX simply does not record this type of activity, aside from a simple page view type of “AJAX” entry.  This was not specific enough, and of course, led to the next question - can we prevent users from downloading data from a grid entirely? I knew that any Javascript-based solution would fall short of their security requirements, since it is trivial to reconstruct the URL pattern required to initiate a download, even if the Javascript had removed the option from the menu.  Thus, I had to consider a PL/SQL-based approach - one that could not be bypassed by a malicious end user. To solve this problem, I turned to APEX’s Initialization PL/SQL Code parameter.  Any PL/SQL code entered in this region will be executed before any other APEX-related process.  Thus, it is literally the first place that a developer can interact with an APEX p