Wednesday, April 11, 2012

Set Initial Focus component for Oracle ADF Faces

Oracle ADF Faces components provide rich functionality out of the box. One small feature is missing somehow:
a convenient way to set initial focus on input component.

For the inpatient readers: sample workspace to download and start with JDeveloper
(11g Release 2) containing a custom tag <adfExt:setInitialFocus/> and a sample usage of it.

<adfExt:setInitialFocus/> features:
  • Drag and Drop usage  from Control Palette in JDeveloper: ADF Extensions -> Set Initial Focus
  • Drop on editable components, like inputText etc.
  • Handles multiple usage of the tag - initial focus is placed on first input component rendered in a view
  • Handles submit on a same view - the focus should stay where it is
  • Handles  properties readOnly, disabled, visible of input component.
    Initial focus doesn't provide much value in case an input component is not visible or read only.
  • Works with regions and therefore with components reused multiple times
The implementation takes advantage of JSF2 (JDeveloper R2)  features like facelets tag library, @FacesBehavior annotation and Behavior API.

NOTE: The principles of implementation can be successfully applied in a previous versions (11g R1 with JSF 1.x) , feel free to take a code and adapt it to your needs.

Steps to get the tag into your web project and use it in JDeveloper Component Palette (directory structure of a sample web project is assumed):
  1. Copy the file  (implementation of the tag) into your project.
  2. Copy the file adfExt.taglib.xml (facelets tag library with a definition of it) into WEB-INF\resources directory 
  3. Add the following context parameter  into web.xml:

Check if tag library is present in JDeveloper Project Properties:

Once configured, a new library ADF Extensions should be available in JDeveloper Component Palette:

There is one component in a library:

Drag and Drop it on some input component, like af:inputText:

Once the page is rendered, a cursor should be placed on that component:

Lets take a closer look to the use case of "Set Initial Focus" component.

User experience

A user opens an input form (built with ADF Faces) to enter some data. The cursor is placed on first editable field, so he can proceed using a keyboard instead of grabbing a mouse first.  After initial focus is set, the user takes a control on cursor position. Once the user took a control and started to navigate ( using TAB or arrow keys), he can finish his work and submit a data entered.

Note: the first input field might not always be the case  - a developer might choose the most suitable component to set initial focus on, based on specific requirements. 

Developer experience 

A software developer might expect to mark a component as a candidate for the initial focus with almost no effort:
  • set a property on appropriate component (initialFocus = true)
  • Drag a control, like "Set Initial Focus" from a component palette in JDeveloper and drop it on the input component of a page.

Implementation challenges

ADF is designed for reusability, especially the bounded task flows facilitate that. One of the challenges covered in this blog post  from Frank Nimphius is related to the naming containers and the naming path: it is not always a case to know it in advance. It results in difficulties to locate a component in Javascript.
Reusable components are (and shouldn't be) not aware about a usage context of them. The simplest way to set a focus is on the other hand to call a Javascript function focus() on component once it has been rendered. We need to get an instance of component in Javascript, therefore need a client Id in order to find it.

ADF Faces provide a build-in AJAX functionality to reload  parts of a page. The implementation using Javascript has to take care about it. In case of partial refresh, a user is still on a same page and doesn't expect the cursor to jump away (see the blog post from Edwin Biemond and the first comment on it).

Addressing the challenges

The implementation of <adfExt:setInitialFocus/> tag is aimed to address the issues described in order to provide an experience  users and developers expect. Some new features provided by JSF2 are used.

One of the features used is Behaviour. See the blog post Das Behavior API with a description of it (oups - it is german link, sorry -  I took a notice about a language only reviewing a post. I leave the link  - modern browsers offer built-in translation, so it helps to google for additional resources in case of interest). My expectation on ClientBehaviour was to get an access to the clientId of component in java code. I'm not sure, if its by design, but one might expect that in case a ClientBehaviour tag is attached, the ADF Faces component renders also a client-peer of it. In that case, there is no need to set a "client Component=true" every time you use initial focus tag. The implementation and my simple tests met the expectation. Drop me a line in case you are familiar with internals of ADF Faces in relation with  ClientBehavior.

Facelets in JSF2 allows to build a tag libraries with ease, so it was selected to provide initial focus functionality for developers as custom tag.

The sources of sample project and implementation are available on public Github repository. In case someone might want to extend, rewrite or fix some issue - it is aimed to facilitate that.

It would be nice to get a feedback on usage of the tag - does it behave in your environment like expected?

To finish the post, a snippet of the source provides the rest of implementation details:

Monday, April 9, 2012

Using Github Gists to embed code snippets

Gists allow to share snippets of code a comfortable way. Below is a code snippet from one public Gist - my random pick to test embedded code and adjust blog layout template:

Follow the link to create your own Gist. Once you create a Gist, click on embed link to get a script tag, copy and paste it into your blog HTML editor like this:

Sunday, April 8, 2012

Snow at Easter time

It is not unusual in April, but still not a regular case to wake up in the morning ant see a snow laying down. Unfortunately,  few hours later it is almost gone.

The post is just a little warm-up to check some features of the Blogger platform.