Saturday, July 2, 2011

ADF Region Handled in a RichPopup - Including a Return Value

I used David Giammona's blog about:

So most of the code kind-of goes as what the blog does as well as what Fusion Dev Guide by F.Nimphius on launching a region within popup... or a popup with a region (forgot the topic title).

My project is setup to log on the following areas.
  • Region task flow entry - just so we know that the task flow has started.
  • On popup launch - this is the part that we handle the switch between an empty region to the actual region
  • On regionNavigationEvent - this is where we handle the programmatic handling of closing the popup. I used a java approach in closing the popup oppose to javascript which is published in paper. This is also the place where i handle the response. The reason for this is because a return from the region is tagged as a null viewId so it is the perfect trigger for me to check for the response which the region throws.
  • On popup close - as you probably already know, this is where i handle the switch to an empty region. Also this listener gets triggered on Cancel, Ok and Escape of the popup.
Anyway, i'll start posting codes.

mainFgmt.jsff

mainFgmt.jsff
As you can see, I'm directly using showPopupBehavior which means that the popup itself will be rendered directly at the same level as this page. So the popup and the view would pretty much have a handle on the scope which of course from the region, you shouldn't try to cross the scope. Later i'll explain more how I decided to handle the parameter passing without the use of contextualEvent.

adfPopupUtils.js

adfPopupUtils.js
Javascript file to handle the call to the serverListener.

FormContentPopupVb.java


FormContentPopupVb.java
This bean (viewScope) handles the dynamic region taskflowId. The switching of taskflowId to/from an empty region. Check for a response which I'll explain more.

FormContent TaskFlow (pageFragment)

formContentPopup.jsff
formContentPopup.jsff
This is the fragment as part of the task flow region that is used inside the af:popup. I have an actionListener which not only navigates for return but also configures the response.

ReturnHandlerBb.java

ReturnHandlerBb.java
This backing bean, as noted will look for the calling popup, search for the region that is directly contained with it (since this is the same region which will handle the regionNavigationEvent), and add an attribute to that component. Yes, there is a potential for this to blowup if the task flow is not used in a popup, but that is why the same utility to retrieve the popup will tell us if this taskflow is being rendered inside one. 

PopupUtil.java

PopupUtil.java
Utility class to retrieve the parent popup.

So as you can see based on the code, the flow of the setup goes like this.
  • Link is clicked which triggers ShowPopupBehavior
  • Popup receives the event and launches which triggers the fetchListener
  • FetchListener handles the configuring of the empty to taskflow to our actual taskflow region
  • Region hits an OK or Cancel and triggers the appropriate ActionListener
  • ActionListener looks for the parentPopup and from there, it retrieves the direct region below it.
  • Configure the RichRegion for an extra attribute which in this case we called "Notification".
  • Return is called by the taskFlow.
  • Region in the calling page triggers RegionNavigationHandler.
  • RegionNavigationHandler closes the popup and also check for the response from the taskflow.
  • OnPopup close, the clientScript is triggered which calls our serverListener.
  • ServerListener makes sure that the dynamic region is reset to an emptyTaskflow.
Cool!

Thursday, June 16, 2011

How to pass multiple parameters to a Bean method from JSF

Having used to java operations, we sometimes find the realm of EL Expression a little short of easy utilities in sending parameters directly from JSF.

This example, while it might not be a standard solution, can provide some easy wins in some situation.

Anyway, here's the code solution.

First thing we need to do is make our own Dummy map which basically implements all of the Map interfaces less the Map.get(Object)


So from this Map, we will try to achieve this :)



So, let's start with the Single Parameter input (I'm just going to show codes from here on since it's pretty straightforward):


And here's its Multiple Parameter counterpart. As you can notice, the more parameters you are handling, the more complicated it can possibly be.

Thursday, June 2, 2011

How to close a TaskFlow Popup Launched Using an af:Popup

Been awhile since I've posted something, so I decided to make a quick and easy hint in ADF.

TaskFlows can be launched as a Popup in a couple of ways in ADF. The most common, I think, is through a taskflow control-case with the following settings:



Then there is the obvious, region in a popup where we drop a fragment taskflow directly inside a popup. I'll show the two common case using a direct popup and a dialog.



The limitation of using it as a direct region though is that the close button is outside the controls of the taskflow, basically, the taskflow itself does not call the close unlike the use of an inline popup as described in the first example. So what happens if we just call the taskflow return from the taskflow? As described in F. Nimphius Fusion Dev Guide, the taskflow itself will close thus closing the binding itself. Here's an example.

Before

After
And forevermore it will remain close unfortunately. Now, to get around this we're going to have the taskflow itself handle situations where it will close the popup without calling the return. To do this, we'll basically retrieve the parent'most component until it is a RichPopup and just call the popup.hide() from there on. So lets go back to coding.

For the fragment, we'll have the return button but this time, it will call an actionListener instead of the controlcase for the return.




Presto. Hope that helps.

Thursday, April 7, 2011

Cascading LOV Using Bounded TaskFlows

This is part 2 of my initial post regarding Bounded TaskFlows used as an LOV.

ADFDeveloper - Applied - #69 Code Corner - LOV Using Bounded TaskFlows

Just as an add-on to my post, I decided to make it one step tricker by introducing a cascading effect in my List-of-Values where data comes from a WebService.

What I'm using is a DropDown of Locations and only Locations which as Departments (since we don't want empty results now hehehe). Of course, we don't want to get lazy now so I also made this DropDown to also use a WebService, and to improve performance, I keep the initial fetch in a ViewScope bean.

Default View

Location DropDown

I also modified the LOV to show the Location registered for the Department, for clarity hehe.

List of Values

The add-on was pretty straightforward, just include it as parameter in the setPropertyListener upon launch of LOV.


TaskFlow

One extra thing that needed to be handled though was the validation. This time around we're not just validating to whether the departmentId is valid, but rather the departmentId needs to be valid based on the set locationId as well.

This part can be implemented in a number of ways, but I chose to add the attribute as part of the validating component.




And there you have it! 2 layers of LOV that relies on a WebService datasource.


Sunday, March 20, 2011

Revising the Dashboard Design - Mixing Stretch and Flowing Layout

This blog is in relation to the Visual Design Demo for the Dashboard.

Upon applying the Dashboard design in one of our projects, which utilizes CRUD transaction as well. The main limitation that was hindering us was how the height of the panelBoxes are limited based on the declared row height in the dashboard. When this  might be tricky since in some scenarios, I would want some items to be higher such as flowing items for form items and some that are stretched for tabular items.

Along with this sample and Andrejus's Blog on the Dynamic Dashboard (http://andrejusb.blogspot.com/2010/02/dynamic-dashboard-ui-shell.html), I am able to achieve this requirement by using a panelGroupLayout scroll to replace the dashboard.

Some of the limitations that I encountered with the default dashboard approach are the following.

  • Depending on the browser, the dashboard optimized render will sometimes fail to render the items correctly
  • Static Height issue
  • If the taskflow is using BackingBean bindings for the component, utilizing the same taskFlowBinding will make the other region not render at all
  • All taskflows will be activated the moment the page loads - I tried lazy loading the taskflows using the activate property but after 2nd activation, it just renders blank.

The main code which allowed me to render some items to flow and some to stretch is the following layout design.


And in case you're missing the part where it scrollToView to the moved item, that is handled by a little javascript to find the component to scroll to.


These combination allowed me to create a modified Dashboard Layout.


If you notice, the Employee PanelBox's height is depending on the amount of fields rendered in it compared to our Department table.

Note: If you need a copy of the full project design for the dynamic dashboard, just send me an email.

Sunday, March 13, 2011

Applied - #69 Code Corner - LOV Using Bounded TaskFlows

I guess to start my spring break blogging, I decided to do a proof of concept regarding the the #69 post in CodeCorner which strikingly is useful especially when your datasource does not rely on a direct database connection.

This blog consists of:

  • WebService design based on BC4J
  • UI ClientProxy consumer that converts the WS objects to map objects for generic usage.
  • TaskFlow LOV Design
  • Consuming page that will use this custom LOV

In my example, I will be utilizing a WS that is driven by BC4J and was designed from WSDL (TOP-DOWN). Using adf wizard to build my webservice classes, I am utilizing a stateless BC4J to service my DepartmentLovService.

For now, this service composes of two operations:

  • FetchDepartments - Allows filter by Location, MaxFetchCount, and WildCard
  • ValidateDepartment - Validates a Department input which can be the name or the id and only checks for a single returned instance

Our query in our ReadOnlyViewObject looks like this.


Pretty much the XSD request are the bindVariables and the response is a DepartmentType with an Id and a Name. That pretty much sets our WebService and using JDeveloper Wizard to create a WebService from WSDL, you should be all set by now.

Now for the Client side, we will still use JDeveloper to create a ClientProxy based on the same WSDL or better yet, the deployed WSDL. By now, on the client side i have 3 static methods.

  • Retrieve a Map of Departments - public static List<Map> retrieveDepartments(Integer fetchCount, String wildCard, BigInteger locationId, BigInteger includedDepartmentId)
  • Check if a departmentId is valid - public static Boolean isDepartmentValid(Integer departmentId)
  • Retrieve the Department information based on the department Id. - public static Map retrieveValidDepartment(Integer departmentId)

All these methods we will use later in our TaskFlow LOV.

We have two taskFlows, one is where our main form is which uses the LOV and one for the LOV taskflow itself. Our main taskFlow is pretty straight forward.



Take note how the button for my LOV is set to immediate. This way, when we consider the input as invalid, we can skip the validation phase so that we can refresh it correctly.

Now for the LOV taskFlow.



We use a pageFlowScope Bean to give us the list of Map which populates the table, and this will also hold all the necessary operations we'll need.


This method's constructor tries to inspect if a departmentId was submitted. This submitted departmentId will be considered as already selected thus we'd like to give the user the feeling that his old selection is still active. Besides that, we also want to filter the fetch count of our WebService. In a real environment, our LOV might contain give or take 300 options, but this will  be such an expensive WS call, so right now we're limiting it by saying "Fetch the first 10 records by default, but also include the record which I've already selected."

Our return selection is triggered when we hit the Ok button in our LOV confirming our new choice. All it does is retrieve the selectedIndex from the table and retrieve this same index from our map as well as set it as our returnParameter (Defined in the taskFlow structure).

Let's go back now to our main calling page and check the returnListener implementation as well as the validation.


This viewBean allows me direct access to my components and input, but even when using the pageDef as binding attributes, you should be able to achieve the same thing.

Return Listener
Let me start explaining the ReturnListener. This return listener tries to inspect the returnParmeters (Map) for return values matching the static key Strings I defined in our LovPageFlowBean. If a value exist, meaning an "OK" was called from the popup instead of a "CANCEL", we are going to first reset the value in the inputComponent using resetValue() this will guarantee that we tell ADF that if the component is invalid, reset it as we are going to set the correct values. After that a partial refresh is called.

Validator
At my first attempt, i was trying to mix the validator and the valueChange as I want to set the dependent field for the departmentName to be updated if the ID being validated is indeed valid. But for a much cleaner separation of the validation and the fetch for additional input, I decided to separate it. All the validator does is call the validate webservice operation, which is a really quick operation checking for atleast a row matching in the WS Side (See query). So all we're doing here is send the ID through the WebService, and websevice responds with a Nay or Yay hehehe.

ValueChangeEvent
So why bother with changeEvent? Because i want to set the outputLabel to show the selected Department when a department is selected from the LoV as well as when I enter a valid department Id.

Notes:
Why didn't I just use one WebService (Fetch) to handle everything?
- I use the fetch operation as my initial entry point of populating my table as well as when the user does a search (wildcard) in the LoV, I would do another re-fetch. Reusing the same WS for the validator might be expensive as this WebService functionality is deliver information while the validator should really be fast and light since it will constantly be called by the lifecycle to ensure all the data i'm sending to the server is valid for processing.

So here's the app demo. Enjoy.



Filter and select value

Select another value but when the initial search is done, always include what's already selected.

There is no department registered in the HR schema with ID set to 5

Set a valid value, and valueChangeListener sets the DepartmentName for you.

Saturday, March 5, 2011

Cascading Dropdown List from Bean

I'll demonstrate how to build a dropdown list where the values are coming from your manage bean. A good useCase for this scenario is when you can't use a BC driven LOVModel and pretty much rely on a manage bean to build your list. In my example, i'm relying on a webservice to return me the list of possible dropdown items which i'll need based on a submitted locationId. On top of it, i keep this list in a pageFlowScope map so that once I have already fetched it, i don't do a refetch especially when i'm asking for the same location's departments.

For my sample, I have a table that contains items (generic) with a location Id. The HR schema has a table of Departments that can be filtered based on this locationId.

So the final running app looks like this.



And yes the departments are filtered based on the locaitonId. So now for the code.

PageFragment

BackingBean

PageFlowBean

A question was raised about how to refresh the list incase there was any dynamic change, the answer to that is to decrease the scope of the bean which holds our map.

Note:
retrieveDepartmentListFromDatasource(locationId) calls a webService to return a list of available departments.