Wednesday Oct 23, 2013

When building a website, there could a requirement to add a tag cloud to let the users know the popular tags (or terms) used in the site. In this blog, we would build a simple declarative component to be used as tag cloud in the page.

To start with, we would first create the declarative component, which could display the tag cloud. We will do that by creating a new custom application from the new gallery.

Give a name for the app and the project and from the new gallery, let us create a new ADF Declarative Component

We need to specify the name for the declarative component, attributes in it etc. as follows

For displaying the tags as cloud, we need to pass the content to this component. So, we will create an attribute to hold the values for the tag. Let us name it as "value" and make it as java.lang.String type.

Once after this, to hold the component, we need to create a tag library. This can be done by clicking on the Add Tag Library button.

Clicking on OK buttons in all the open dialogs would create a declarative component for us. Now, we need to display the tag cloud based on the value passed to the component. To do that, we assume that the value is a Tree Binding and has two attributes in it, say "Name" and "Weight". To make a tag cloud, we would put together the "Name" in a loop and set it's font size based on the "Weight". After putting our logic to work, here is how the source look

Attributes added to the declarative components can be retrieved by using #{attrs.<attribute_name>}. Now, we need to deploy this project as ADF Library Jar file, so that this can be distributed to the consuming applications.

We'll select ADF Library Jar as type and create the profile.

We would be getting the jar file after deployment.

To test the functionality, we could create a simple Fusion Web Application.

To add our custom component to the consuming application, we can create a file system connection pointing to the location where the jar file is and add it or, add through the project properties of the ViewController project.

Now, our custom component has been added to the consuming application. We could test that by creating a VO in the model project with a query like,

select 'Faces' as Name,25 as Weight from dual union all select 'ADF', 15 from dual union all select 'ADFdi', 30 from dual union all select 'BC4J', 20 from dual union all select 'EJB', 40 from dual union all select 'WS', 35 from dual

Add this VO to the AppModule, so that it would be exposed to the data control. Then, we could create a jspx page, and add a tree binding to the VO created.

We can now see our Tag Cloud declarative component is available in the component palette.

It can be inserted from the component palette to our page and set it's value property to CollectionModel of the tree binding created.

Now that we've created the Declarative component and added that to our page successfully, we can run the page to see how it looks.

As per the query, the Tags are displayed in different fonts, based on their weight.

Let us assume a usecase where we have some text fields with auto
suggest feature enabled, and their suggested items could be
dependent on one other. For ex : Country, State and City.

This could be modeled by having an EO and VO created based on
Person table and read-only look-up VOs created based on Country,
State and City tables.

Implementing the dependency between LOVs is pretty straight
forward. However, implementing the dependency between the auto
suggest items is not. In order to achieve the dependency, first we
would need couple of methods returning current row's CountryId and
StateId. We could add them up in the AMImpl class.

As we need to filter out the States based on the Country and the
City based on the Country & State, we would need to modify the
query of these two VOs to include a bind variable in the where
clause.

For having the auto suggest, we need to have a view criteria
defined for all the three look-up VOs (CountryView, StateView and
CityView).

Generate VOImpl classes for Country, State and City VOs (with
Include bind variable accessors option checked), and then expose
setBindCountryName (in Country VO), setBindStateName (in State VO)
and setBindCityName (in City VO) methods as client interfaces.

And the last part on the model is to pass the current row's
CountryId and StateId to the Bind Variables defined in the State
and City VOs. Also, we need to get the VCs created above to be
executed by default (By editing the VO instance in the AM's data
model), so that the auto suggest list would be filtered as and when
the users type.

Here, we specify groovy expression for the CountryId and StateId
as adf.object.applicationModule.<methodName>. For more
information about using groovy expressions, check out this :
http://www.oracle.com/technetwork/developer-tools/jdev/introduction-to-groovy-128837.pdf
.

With this, we are done with setting up the model layer for the
auto suggest dependency.

In the View layer, we would create an ADF Form based on the
Person VO, with all the navigation buttons.

In order to construct the onSuggest items, we would create Tree
Bindings for Country VO, State VO and City VO, along with method
action bindings for the setBindCountryName, setBindStateName and
setBindCityName methods.

Now, we could add af:autoSuggestBehavior for CountryId, StateId
and CityId fields. Then, add onSuggest methods in backing bean for
populating the on suggest items for each fields.

Monday Nov 26, 2012

When using AutoSuggestBehavior for a UI Component, the auto
suggest list is displayed as soon as the user starts typing in the
field. In this article, we will find how to restrict the
autosuggest list to be displayed till the user types in couple of
characters.

This would be more useful in the low latency networks and also
the autosuggest list is bigger. We could display a static message
to let the user know that they need to type in more characters to
get a list for picking a value from. Final output we would expect
is like the below image

Lets see how we can implement this. Assuming we have an input
text for the users to enter the country name and an autosuggest
behavior is added to it.

Also, assuming we have a VO (we'll name it as CountryView for this
example), with a view criteria to filter out the VO based on the
bind variable passed.

Now, we would generate View Impl class from the java node
(including bind variables) and then expose the setter method of the
bind variable to client interface.

In the View layer, we would create a tree binding for the VO and
the method binding for the setter method of the bind variable
exposed above, in the pagedef file

As we've already added an input text and an autosuggestbehavior
for the test, we would not need to build the suggested items for
the autosuggest list.Let us add a method in the backing bean to
return us List of select items to be bound to the autosuggest
list.

So, what we are doing in the above method is, to check the
length of the search term and if it is more than 1 (i.e 2 or more
characters), the return the actual suggest list. Otherwise, create
a read only select item

new SelectItem("","Type in two or more characters..","",true);

and add it to the list of suggested items to be displayed. The
last parameter for the SelectItem (boolean) is to make it as
readOnly, so that users would not be able to select this static
message from the displayed list.

Friday Aug 10, 2012

There are quite a number of documentations / blogs on creating cascading (dependent) list of values in ADF Application using BC4J as model.

Some examples

1. https://blogs.oracle.com/shay/entry/got_to_love_cascading_lovs_in

2. http://mjabr.wordpress.com/2011/04/01/cascade-list-of-values/

However, these entries talk about creating list of values for master-detail attributes. In this article, I would be explaining about creating list of values which have master-detail-grand detail relationship (though the implementation is same, the use case is different).

Assuming that we've our model ready, with an VO for Person (based on Person EO), Country, State and City (read-only VOs).

Now, we'll modify the query of the dependent VOs to include a bind variable in their where clause.

We could then create List of Values for the CountryId, StateId and CityId attributes in the Person VO.

Above image shows an example for creating LOV for the CityId attribute. LOV is created for the CountryId and StateId attributes in the similar fashion.

Now that we've created LOV for all the 3 attributes, we need to pass the required values for the bind variable we created previously (in State and City VOs). That is done from the View Accessors tab of Person VO.

Now we are set to go with the dependent LOV. Before running the Tester, we need to make the CountryId and StateId attributes automatically submit their values upon change (by setting Auto Submit UI Hint to true)

(Above image shows setting Auto Submit UI Hint to true for CountryId attribute. In the same manner, set the Auto Submit UI Hint to true for the StateId attribute as well).

and add make StateId dependent on CountryId, CityId to depend on CountryId and StateId.

We are set to go now. Run the AppModule tester to verify the values.

When using this in jspx page, set the AutoSubmit properties for the CountryId and StateId components, and add the partialTriggers for StateId and CityId components with the Id of CountryId component, as shown below.

Hint: Right click on the images and select View Image to view it completely if it is cropped.

Usecase :
Show a warning to user when they try to search the records (af:query
component), without specifying a criteria / a wild card "%". I.e, when
the user tries to query the entire table, show a warning that querying
all the records would take some time.

There are three phases in implementing this usecase.

1. Interpret the query event and get the query criteria.2. Show the popup.3. Process the interpreted query based on the outcome of the popup.

Before proceeding with the implementation, we'll create a page for assumption.a. Page contains a af:query component with a resultant table / read-only table.b. Has a popup to be shown to the end user.c. Bound to a bean.

We'll now implement it phase by phase.

First of all, we'll create couple of attributes in the bean and generate accessors to them.

<af:popup childCreation="deferred" autoCancel="disabled" id="p1">
<af:dialog id="d2" type="yesNo" title="Are you sure?"
dialogListener="#{viewScope.QueryBean.onDialog}">
<af:outputText value="It would be time consuming to query for all
records. Are you sure you want to continue?" id="ot9"/>
<f:facet name="buttonBar"/>
</af:dialog>
</af:popup>

Thursday Jul 12, 2012

In some scenarios, we would need to calculate the time elapsed since the
last query execution, without contacting the server (i.e without using
af:poll component). This blog is to give an example for this scenario by
using javascript.

This function finds the outputText (with id ot9), resets its value (i.e set it to blank) and then schedules the function we've created first (updateTimer()) to be called every minute (i.e 60000 milliseconds).

Assuming we have a button to execute the query, we'll add a client listener to the button to execute this function when pressed.