ADF Faces RC has built in support for AJAX and Partial Page Refresh. Through the autoSubmit and partialSubmit attributes, we can indicate that a value change or an action (button or link click) should trigger an asynchronous request (PPR request). Through the partialTriggers attribute, we can configure components to be refreshed in any PPR request that is initiated by the a component whose Id is listed in the partialTriggers attribute. So you can say that through the partialTriggers attribute, we register a component as PPR listener on all components listed in the attribute value.
Sometimes, developers would like to be able to do it the other way round. To specify on a component X which other components should be refreshed when X is initiating a PPR request. In this article, we will discuss a method for doing exactly that.We will use a very simple example of an outputText that displays the value of the counter property of a managed bean. The page contains a commandLink. When this link is clicked, the counter is incremented and we would like the outputText to be (partially) refreshed.
The usual approach for this: set partialSubmit to true for the link and include the commandLink component’s ID value in the partialTriggers attribute of the outputText:
<af:panelLabelAndMessage id="counterLabel" label="Counter" for="counter"> <af:outputText id="counter" value="#{CounterBean.counter}" partialTriggers="increment" /> </af:panelLabelAndMessage> <af:commandLink id="increment" text="Increase and Refresh Counter" actionListener="#{CounterBean.increaseCounter}" partialSubmit="true"> </af:commandLink>
In this case, we will turn that around. The instruction to refresh the outputText when the link is activated is added to the commandLink.
<af:panelLabelAndMessage id="counterLabel" label="Counter" for="counter"> <af:outputText id="counter" value="#{CounterBean.counter}"/> </af:panelLabelAndMessage> <af:commandLink id="increment" text="Increase and Refresh Counter" actionListener="#{CounterBean.increaseCounter}" partialSubmit="true"> <af:setPropertyListener from="counter" to="#{PartialTargetManager.partialTarget}" type="action"/> </af:commandLink>
The mechanism used in this approach is a generic PartialTargetManager with a setPartialTarget method that accepts a string that should hold the id for the component that should be refreshed. The setPropertyListener will fire when the link is activated (type=’action’) and will pass the string value "counter" (the id of the outputText component) to this setter method.
The PartialTargetManager bean is implemented as follows:
public class PartialTargetManager { public void setPartialTarget(String componentId) { UIComponent component = FacesContext.getCurrentInstance().getViewRoot().findComponent(componentId); if (component!=null) { AdfFacesContext context = AdfFacesContext.getCurrentInstance(); context.addPartialTarget(component); } } }
The setPartialTarget method tries to find the component specified in the ViewRoot. When found, the component is passed to the list of partial targets in the AdfFacesContext.
The bean is configured in faces-config.xml:
<managed-bean> <managed-bean-name>PartialTargetManager</managed-bean-name> <managed-bean-class>view.PartialTargetManager</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean>
<managed-bean> <managed-bean-name>Counter</managed-bean-name> <managed-bean-class>view.Counter</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean>
The Counter bean is trivial:
public class Counter { private Integer counter =0; public Integer getCounter() { return counter; } public void increaseCounter(ActionEvent event) { counter++; } }
When we run the page, the outputText and its label are displayed as well as the action link. Clicking the action link will lead to an increased value in the counter value – through PPR that was declaratively instructed from the perspective of the link to refresh the outputText.
Download JDeveloper 11g sources componentToComponentPPR.zip .