Live resource bundle entry editing in a generic way through declarative component and UI component tree manipulation image165

Live resource bundle entry editing in a generic way through declarative component and UI component tree manipulation

In a series of five articles I have discussed how boilerplate text elements such as prompts and labels could and should be taken out of pages and centralized in resource bundles. I have explained how resource bundles can be implemented in database tables, how the bundles can be refreshed at run time and how different user groups can be served with different resource bundles. The previous article demonstrated how text properties can be edited at run time, in the context of the application.

image

The approach discussed for live text editing works fine. However, its current implementation requires specific manipulation – of every individual page. Each page contains a popup component and each component to be edited needs to have an associated showPopupBehavior or even a commandImageLink.

This article outlines a more generic approach that requires virtually no page or component specific preparation. The popup is takes out of the page into a page fragment. This page fragment is included in every page using a single declarative component tag. Via a phaseListener on the f:view tag, the UIComponent tree of every page is programmatically manipulated before being rendered. The manipulation consists of adding showPopupBehavior children to all UIComponents with textual properties.

The manipulation of the UIComponent tree is a fine way to influence the appearance of any JSF application at run time, based for example on meta data that can also be managed at run time. I have made use of this approach on several occasions.

1. Move the popup from the page to a fragment and include the fragment as declarative component

The popup component is copied to a JSFF file:

image

The popup is subsequently included into PageOne.jspx (and every other JSPX file) through a declarative component:

image

Note: because the declarative component is a naming container, the reference to the popup in the showPopupBehavior components is changed from just editTextResources to texteditPopup:editTextResources.

2. Run Time manipulation of the UIComponent tree

Define managed beans

image

Configure f:view component

image

Implement the phaseListener bean

image

Implement the UI Component Tree manipulator bean PageProcessorForTextEditing

The page can be in text editing mode (or not). This is determined by a property on the pageProcessorForTextEditing bean. The toggle between textEditing mode and non-textEditing mode is made using a commandLink:

image

in code this looks like this:

image

Whenever the commandLink is clicked to enter text editing mode, the page is re-rendered and before rendering takes place, the viewPhaseListenerBean steps in and calls the processPage() method in the pageProcessorForTextEditing bean. This method traverses the UI Component Tree and calls upon a helper method to add the showPopupBehavior listeners.

image

The method addPopupBehaviorOnUIComponent programmatically creates the equivalent of the <af:showPopupBehavior> component, associated with the text editor popup:

image

The method componentIsTextEditable verifies whether the component is one that we want a showPopupBehavior added to:

image

The findClientListenerSet() method inspects a UIComponent and tries to locate its clientlistenerset. If it does not exist, it finds out whether the UIComponent is an ADF Component that supports clientListeners (i.e. exposes a method getClientListeners()). If it does, a new ClientListenerSet is instantiated and set on the component.

image

 

Alternative UI facilities for opening the popup text editor

Using a mouseOver – or double click – to trigger the popup works okay, but is a little implicit. The user needs to know what to do. There are ways of implementing more visual, more explicit access points for the user. An example is the context facet:

image

the little orange square that the user can hover over:

image

when clicked, the popup editor will open.

This context facet can be added programmatically using this code:

image

Note that only input components such as inputText and selectOneChoice support the context facet.

Also note that a small modification is required in the populateProperties() method in class TextEditor to recognize the RichContextInfo and ensure that the textual properties are shown for the parent of the context component:

image

Another UI widget that we can add programmatically to make access to the text editor more explicit is through the use of a commandImageLink:

image

The code that will add this commandImageLink:

image

This code is invoked for CommandButton components:

image

 

Resources

Download the ADF application with the code demonstrated in this article: ADFFacesWithResourceBundle_Step7_DynamicUITreeManipulation.

Other articles in this series:

  1. Introduction to Resource Bundles in ADF applications for centralizing (management of) boilerplate text

  2. Implement resource bundles for ADF applications in a database table

  3. Supporting multiple languages in ADF applications backed by resource bundles – and programmatically controlling the JSF locale

  4. Adding customization (or context sensitivity) to boilerplate text from database backed resource bundles in ADF applications

  5. Refresh resource bundle from within the ADF application – to absorb changes in database backed bundles

  6. Live update of Resource Bundle from within running ADF application

  7. Live resource bundle entry editing in a generic way through declarative component and UI component tree manipulation

  8. Creating reusable ADF Library with generic live resource bundle editing functionality and reusing it in any ADF application