Oracle ADF - Why won't my af:outputText refresh?

This is a guest post from my coworker Maria Kaval.

I'm working on a project to build a Hangman Game using Oracle ADF. For those not familiar with this game, there is a secret word, and the user needs to guess letters in the word in order to unveil what the word is. For each letter correctly guessed, the letters of the word are shown. For each letter incorrectly guessed, one of the colors in the image is removed. The user wins once they can guess the word. The user loses if all the colors in the picture are gone. In the screen shot below, the secret word is "APPLE".

Hangman.PNG

If the user presses the letter "A", the secret word is updated, and the button for letter A is hidden from the user.

HangmanA.PNG

If the user presses the letter "X", there is no match, so the secret word does not need to update, and the letter X is hidden from the user.

HangmanX.PNG

In building this game application, I've run into a few scenarios where a component doesn't refresh as I would expect it to. I will explain those in greater detail below.

Scenario 1: No Client Component


Assume the user presses one of the alphabetic letters in the Hangman Game. If the letter is a match to one of the letters in the word, I need to refresh the letter in the word from underline ( _ ) to that letter. For example, if the word is "APPLE", and the user sees "_ _ _ _ _", presses the letter "A", then I would want the outputText to refresh to "A _ _ _ _". However, if the user presses a letter, e.g. "X", which is not a match, I don't want to refresh the outputText. In order to selectively have the outputText refresh, I don't set the partialTrigger on the outputText, but instead in the actionListener on the commandButton behind each alphabetic character, I check whether or not that letter is a match, and if it is, I explicitly call AdfFacesContext.getCurrentInstance().addPartialTarget(ot1), passing in the id of the outputText component, thereby forcing a refresh. However, even though I was calling addPartialTarget programatically the outputText was not refreshing! The problem is that outputText is designed to be as performant as possible, so there is not client side object for the outputText unless the framework can detect that one is needed. In the case where the application developers is adding the partialTarget in the java code, the framework can't automatically detect that the outputText client component is necessary, and so none is generated and hence there is nothing to refresh. In order to work around this I need to set the clientComponent attribute to true on the outputText.

To make this easier to understand, assume we have a simple Hello World! App where the user types in their name, clicks on a "Hello" button and then in an outputText field below it prints out "<name>", using whatever value was entered by the user in the input field. Normally you would set partialSubmit="true" on the commandButton, and then set the partialTrigger to the commandButton's id on the outputText, e.g.:

  1 <af:inputText label="Name:" 
  2               id="it1" 
  3               value="#{backingBeanScope.backing_pprTest.name}"/>
  4 <af:commandButton text="Hello" 
  5                   id="cb1"
  6                   partialSubmit="true"/>
  7 <af:outputText value="#{backingBeanScope.backing_pprTest.name}" 
  8                id="ot1"
  9                partialTrigger="cb1"/>

HelloWorld.PNG

However, in my Hangman example, I don't want the outputText to refresh each time the button is pressed, but instead to only refresh if certain conditions are true. Assume the same with this Hello World example. So then, I write an actionListener for the commandButton which will evaluate logic to determine whether or not to refresh the outputText. In order to be able to access the outputText in my action listener, I EL bind the binding attribute on the outputText attribute.

  1 <af:inputText label="Name:" 
  2               id="it1" 
  3               value="#{backingBeanScope.backing_pprTest.name}"/>
  4 <af:commandButton text="Hello" 
  5                   id="cb1"
  6                   partialSubmit="true"
  7                   actionListener="#{backingBeanScope.backing_pprTest.welcome}"/>
  8 <af:outputText value="#{backingBeanScope.backing_pprTest.name}" 
  9                binding="#{backingBeanScope.backing_pprTest.ot1}"
 10                id="ot1"/>

and then in my backing bean I have:

  1 public void welcome (ActionEvent e)
  2 {  
  3   AdfFacesContext.getCurrentInstance().addPartialTarget(ot1); 
  4 }
  5 
  6 RichOutputText ot1;
  7 public void setOt1(RichOutputText ot1)
  8 {
  9   this.ot1 = ot1;
 10 }
 11 
 12 public RichOutputText getOt1()
 13 {
 14   return ot1;
 15 }

But the outputText doesn't refresh!! The issue is that the outputText is designed to be as performant as possible. As such, it doesn't have a client-side implementation. So when we call addPartialTarget and pass in the outputText component, there is nothing on the client to refresh. In order to ensure there is an object on the client that can be refreshed, we need to set clientComponent attribute to true on the outputText, like this:

  1 <af:inputText label="Name:" 
  2               id="it1" 
  3               value="#{backingBeanScope.backing_pprTest.name}"/>
  4 <af:commandButton text="Hello" 
  5                   id="cb1"
  6                   partialSubmit="true"
  7                   actionListener="#{backingBeanScope.backing_pprTest.welcome}"/>
  8 <af:outputText value="#{backingBeanScope.backing_pprTest.name}" 
  9                binding="#{backingBeanScope.backing_pprTest.ot1}"
 10                id="ot1"
 11                clientComponent="true"/>

By setting clientComponent to true, I guarantee that there is a client-side representation of the outputText, and my Hello World! app works as I expect.
HelloWorld2.PNG

Scenario 2: Need to refresh the parent container instead of the actual object

Stay Tuned!


Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

An exploration in the lighter side of ADF development.

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today