JDeveloper: Advanced Skin Technique

This post is about an advanced technique to change the look and feel of an ADF application. Changes to the look & feel are normally done via a skin which you use to change descriptors which are used by the ADF components. The general technique to do this is described in many blogs and articles like ADF Faces Skin Editor – How to Work with It and the official documentation at Oracle ADF Skin Editor.

In this blog we look at an advanced technique which helps to change the look and feel of components like af:query and pf:panelCollection which you can’t change using the normal available descriptors. In the below image you see the Skin Editor showing the ADF components skin descriptors.

selection_985

Use Case

In this use case we work with the af:panelCollection component. This component is used to wrap af:tree, af:treeTable and af:table components to provide additional functions. From the documentation of af:panelCollection

A panel component that aggregates collection components like table, treeTable and tree to display standard/application menus, toolbars and statusbar items.

The default top level menu and toolbar items vary depending on the component used as the child of the panelCollection.

  • For table, tree and treeTable, the default top level menu item is View.
  • For table and treeTable with selectable columns, the default top level menu items are View and Format.
  • For table and treeTable, the default toolbar item is Detach.
  • For table and treeTable with selectable columns, the default top level toolbar items are Freeze, Detach and Wrap.
  • For tree and treeTable, if the pathStamp facet is used, the toolbar buttons Go Up, Go To Top, Show as Top also appear.

The component allows us to switch off some function

Value Turns off
statusBar Status bar
viewMenu ‘View’ menu
formatMenu ‘Format’ menu
columnsMenuItem ‘Columns’ sub-menu item
columnsMenuItem:col1,col20 Columns with column ID: ‘col1’ and ‘col20’ inside ‘Columns’ sub-menu
freezeMenuItem ‘Freeze’ menu item
detachMenuItem ‘Detach’ menu item
sortMenuItem ‘Sort’ menu item
reorderColumnsMenuItem ‘Reorder Columns’ menu item
resizeColumnsMenuItem ‘Resize Columns’ menu item
wrapMenuItem ‘Wrap’ menu item
showAsTopMenuItem Tree/TreeTable ‘Show As Top’ menu item
scrollToFirstMenuItem Tree/TreeTable ‘Scroll To First’ menu item
scrollToLastMenuItem Tree/TreeTable ‘Scroll To Last’ menu item
freezeToolbarItem ‘Freeze’ toolbar item
detachToolbarItem ‘Detach’ toolbar item
wrapToolbarItem ‘Wrap’ toolbar item
showAsTopToolbarItem Tree/TreeTable ‘Show As Top’ toolbar item
wrap ‘Wrap’ menu and toolbar items
freeze ‘Freeze’ menu and toolbar items
detach ‘Detach’ menu and toolbar items

As a sample the image below shows a normal af:panelCollection (upper half) and an af:panelCollection with the view menu and the toolbar switched off (lower half)

selection_979

Looking at the possible things to switch off we don’t see anything to switch off the ‘Query by Example’ (QBE) icon. There is no feature toggle to turn this function on or off. An easy way to get rid of the icon would be to make the table not filterable. However, if we like the table to be filterable but don’t want to show the icon to switch the feature off, we have to use an advanced skin technique.

What can we do to get rid of the icon in the tool bar?

The idea is to use a skin or special css to hide the icon or the container which holds the icon. To find the container we first inspect the page in the browser using the browsers ‘Developer Tools’ which you can reach by hitting F12 in your browser. Below you see Chrome 55 with activated ‘Developer Tools’

Selection_211.jpg

The image shows the toolbars QBE image as selected element on the page (left red rectangle) and the style classes which are in use for this element (right red rectangle). The names ‘.xfo’ and ‘.xfr’ are the names of the style classes. They are minimized to reduce the download size of the page, but they are not ‘readable’. 

The first thing to do is to make the names ‘readable’ for us. We need to know which skin selector generated the style class. For this we set a context parameter in the web.xml file

 <context-param>
 <param-name>org.apache.myfaces.trinidad.DISABLE_CONTENT_COMPRESSION</param-name>
 <param-value>true</param-value>
 </context-param>

Setting this parameter to true will show us the clear names. The image below shows the same selection only this time with the real names

selection_212

One other nice feature of the ‘Developer Tools’ is that you can inspect elements by just hover over them on the page. This allow us to easily find the element we want to hide via css. Click on the icon marked in hte below image

selection_213

and move the mouse cursor over the page. You see the HTML and the active styles of the element under the cursor. This feature we use to find an element which holds the icon we want to hide and which we can address via css .

selection_214

CSS allows us to address elements inside a skin selector.  For this you need to know the skin selector, the tag or container and it’s ID inside the selector you want to address. In the image above we see the ID of the icon container we want to hide as “id=’pc1:_qbeTbr'” and the container or tag itself which is a ‘div’. The skin selector is the af|panelCollection. With this information we can can change the style attached to the ‘div’ container with the id ‘*_qbeTbr’  in the af|panelCollection as

af|panelCollection div[id$='_qbeTbr'] {
    display: none;
}

This we can add to our skin.css file. However, if we just add it this way it’s changing all af:panelCollection in our application.  If we want this only to be active for specific af:panelColletion we can add a style class name like

af|panelCollection.myPCClass div[id$='_qbeTbr'] {
    display: none;
}

Now we can add the stale class name ‘myPCClass’ to the af:panelCollection when we like the QBE icon not to be shown

 <af:panelCollection id="pc1" styleClass="myPCClass">
   <f:facet name="menus"/>
   <f:facet name="toolbar"/>
   <af:table value="#{bindings.EmployeesView1.collectionModel}" ...
   ...
 <af:panelCollection id="pc2" featuresOff="detachToolbarItem viewMenu">
 <f:facet name="menus"/>
 <f:facet name="toolbar"/>
 ...

will generate this UI output

selection_217

 

As we see, the QBE icon is gone. In the original page we have placed two af:panelCollection components. As you added the new style class only to one of them, the other QBE icon is still visible.

Extending

You can use hte same technique for other complex ADF components like af:query. Here you can style the save button which normally not  supported.

Download

You can download the sample which is build using JDev 12.2.1.2.0  and uses the HR DB schema from GitHub BlogAdvancedSkin

Book Review: Oracle ADF Faces Cookbook by Amr Gawish

During my short vacation I spend some time reading books. One of them was ‘Oracle ADF Faces Cookbook’ by Amr Gawish (http://bit.ly/PhWTlR).

Oracle ADF Faces Cookbook

Oracle ADF Faces Cookbook


The book is written as a cookbook, as the name says, for ADF Faces in the version 12c (12.1.2.0.0 to be accurate). The book offers 10 chapters:

  1. Building Your ADF Faces Environment From the Ground Up
  2. Here you get information about how to install JDK 1.7, Oracle XE Database, JDeveloper and how to tune the environment to work best together. Finally you can download the code used throughout the book from a GIT repository.Make sure to download the code and have it ready while reading the book!

  3. Getting Started with ADF Faces and JDeveloper
  4. In this chapter you get the very basics about development of Fusion Web Applications, building an workspace, connection to the DB, creating a business service, defining page flows and pages and how to run an ADF Faces application from within JDev.

  5. Presenting Data Using ADF Faces
  6. Here we start with use cases used for presenting data. You get info on how to present single records and different master – detail use cases, using different techniques. Finally a first glance on internationalization.

  7. Using Common ADF Faces Components
  8. Here you get a walk through to the normal adf faces components for input, output, selection, loading of data as well as pop-up, code editor, menu model, links, trains and dynamic components.

  9. Beautifying the Application Layout for Great User Experience
  10. Is about page templates, skins, responsive design and flat design techniques.

  11. Enriching User Experience with Visualization Components
  12. This chapter handles maps, graphs, gauges, Gantt charts, hierarchy, sunburst and timeline components.

  13. Handling Events and Partial Page Rendering
  14. Here events (client and server), partial triggers and behavior components are introduced. Polling, Drag & Drop, Active Data Service and WebSocket are described too in this chapter.

  15. Validating and Converting Inputs
  16. Is about conversation of data, custom converters, validation (client and server) and faces messaging.

  17. Building Your Application for Reuse
  18. Picking up from chapter 2 we learn about page templates, exception handling task flow parameters, contextual events, ADFLibraries and finally Meta Data Service (MDS).

  19. Scaling your ADF Faces Application
  20. The final chapter is about performance and recommendations as well as some advances options like Content Delivery Network (CDN) and ADF caching of resources.

The cookbook uses its own db schema which looks kind of familiar, as it’s build from the well known HR schema.

While reading the book I found some recipes hard to understand for novice developers, without reading the provided code in parallel. This is because the book is all about ADF Faces but spares most about the ADF Business Components Model layer. Here the reader has to know how things are working and how to set things up.
For experienced developers some of the covered topics are nothing new, we work with them every day. The uses cases covered are mostly basic in nature and you often see links to the original documentation. Here you find the missing information which is not covered in the cookbook itself. I would have liked some more deep going information on how properties work together for some often used components like af:table or af:panelGridLayout.

I personally found it hard to understand why the author used task flows build from pages for some of the use cases just because ‘it’s easier’. One of the main advantages are task flows build of fragments. They allow reuse and help divide a task into smaller pieces. Tools like the ADF-EMG Task Flow Tester are not even mentioned. Using this tool makes it easy to run task-flows build on fragments without the need to build a JSF Page to host the region.
There are no use cases which handle region specific questions like when regions are refreshed or how regions are restarted. Transaction management and data control sharing are not covers too.

The real interesting part of the book starts with chapter 5, where page templates, skins and at least some layout techniques are introduced. Very interesting is the use case about using SAAS (Syntactically Awesome Style Sheets) and Compass to build more dynamic css files which can be used in ADF. The chapter covers Responsive Web Design and Flat Design Techniques (which are trying to minimize the design) too.

Also interesting are the samples which are build in chapter 6 for graphs, gauges, maps, pivot table, Gantt charts (calendar is missing), timeline and sunburst. However I personally find them hard to digest as they have many ingredients (steps in this case) which you have to follow. Again the model layer is pre-build for you, which means you have to find out yourself how and if there are something special in the model to cook the dish. Nevertheless, samples in this area are hard to find, and these samples do work!

The chapter about event handling and ppr is a very nice summary of how things work in ADF. Easy to understand samples are making it easy to follow the concepts. Here you find samples for ADS (Active Data Service) and WebSocket too. Nice!
Contextual events are handled in a later chapter (‘Building Your Application for Reuse’) but they are not described in great detail. It’s enough to get a first impression.

The final chapter is a nice summary of performance increasing methods and techniques which is worth reading. After reading the techniques it make sense to test them on your system!

Summary:
Novice developers learn basic ADF Faces techniques and components by building samples. Some recipes are too complicated to understand by just reading them. As the book uses its own DB schema you should have this ready, as well as the code, to work through them.

JDEV: af:query hide ‘Add Fields’ from query panel via custom skin

In my last post ‘JDEV: af:query hide some attributes from query panel but show them in the result table’ I showed how to hide some of the available attributes from the af:query panel.
Juan, an other blogger informed me that he too had shown how to do this (Control visibility of a query in adf). The blog not only showed how to hide attributes from the panel, but also showed how to hide the ‘Add Fields’ button you see in the advanced mode.

Query Panel Advanced Mode

Query Panel Advanced Mode


The method (or better trick) is to put a component in the footer facet of the af:query, which is stated in the docs. If you use an af:spacer (e.g. 1×1) for this, nothing is visible in the panel. The automatically filled in button ‘Add Fields’ is gone.
Well, I’m not just copying the other blog, but like to show a different approach using a custom skin to do it. The advantage using the skin approach is that you can clearly see (via hte name of the style class) why you don’t see the ‘Add Field’ button. Using the spaces the button is simply gone and you have to remember how you get rid of it (in a year).

First we need to add an ADF Skin to the project. For this we add a new ADF Skin file to the project and set its properties:

Skin creation

Skin creation


Skin Properties

Skin Properties

As I’m using JDev 11.1.2.1.0 the skin editor is build in. If you are trying this on an older version, you can use the stand alone version to create the skin file.
In the skin editor we look for the af:query component, which we want to change. In the component properties for the af:query we look for the ‘footer-facet-content-style’ pseudo element. For this element we set the display property to none. This will hide the whole facet in the UI. As this facet holds the ‘Add Fields’ button, the button is not visible in the UI.

Change Element

Change Element

Preview of af:query with skin applied

Preview of af:query with skin applied

If you leaf the skin in this state, the change works for all af:query components of hte project. As I like it to be changeable on a per component basis, I define my own style class for this change. For this change to the source mode of the skin file and add a style class name in front of the selector:

/**ADFFaces_Skin_File / DO NOT REMOVE**/
@namespace af "http://xmlns.oracle.com/adf/faces/rich";
@namespace dvt "http://xmlns.oracle.com/dss/adf/faces";

.AFQueryHideAddFields af|query::footer-facet-content-style
{
  display: none; 
}

Now you can use this ‘AFQueryHideAddFields’ style class on each af:wuery component where you want to hide the ‘Add Fields’ button .

...
                    <af:query id="qryId1" headerText="Search" disclosed="true"
                              value="#{bindings.ImplicitViewCriteriaQuery.queryDescriptor}"
                              model="#{bindings.ImplicitViewCriteriaQuery.queryModel}"
                              queryListener="#{bindings.ImplicitViewCriteriaQuery.processQuery}"
                              queryOperationListener="#{bindings.ImplicitViewCriteriaQuery.processQueryOperation}"
                              resultComponentId="::pc1:resId1" styleClass="AFQueryHideAddFields">
...
Apply StyleClass

Apply StyleClass

You can download the sample workspace, build with JDev 11.1.2.1.0 and depending on hte HR db schema, from here: BlogHideAttributesInQueryPanel_v2.zip
Please rename the file to ‘.zip’ after downloading it!