In a recent article (Client Side Event Bus in Rich ADF Web Applications – for easier, faster decoupled interaction across regions), I proposed an approach for a client side event bus in ADF Faces Web Applications – as light weight, straightforward, simple alternative to contextual events. The article demonstrated how a client side event in a fragment in a nested taskflow was published, routed and consumed in a different taskflow, leading to a relevant response to the user action.
In this article I have slightly extended the example.
The consuming fragment will now also send a custom event to the server, informing the server side backend for the consuming fragment of the client side news. Specifically: the menu taskflow consumes the color selection event. It updates the radio group selection accordingly (client side).
Next, it pushes the newly selected color via a serverlistener to its backing bean. This bean updates a managed property and orchestrates the partial refresh of one of the UI components. The user will see the backcolor changing of the menu area in the page as a result of this partial refresh.
It is important to realize that the server action in the Menu taskflow is triggered by the client side components of the Menu taskflow – and not directly by the server side of the taskflow in which the triggering user event took place.
In a somewhat complex picture, this is the flow:
The code changes over and above the situation after the previous article are limited.
- The MenuBean class is added and a managed bean menuBean is configured for the menu-taskflow based on this class. The class contains a managed property (color) and a method to handle the client event that is sent when the color selection took place in the client. This method will adjust the managed property according to the selection in the client and partially refresh the PanelGridLayout component.
package eventbus.view.menu; import java.util.Map; import oracle.adf.view.rich.component.rich.layout.RichPanelGridLayout; import oracle.adf.view.rich.context.AdfFacesContext; import oracle.adf.view.rich.render.ClientEvent; import org.apache.myfaces.trinidad.util.ComponentReference; public class MenuBean { public MenuBean() { super(); color="green"; } private ComponentReference ColorPanelGridLayout; private String color; public void handleColorSelection(ClientEvent ce){ // get payload of custom event - that we know should contain the selected color Map<String, Object> map = ce.getParameters(); String newColor = (String) map.get("newColor"); setColor(newColor); AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance(); adfFacesContext.addPartialTarget(getColorPanelGridLayout()); } public RichPanelGridLayout getColorPanelGridLayout() { if (ColorPanelGridLayout!=null) { return (RichPanelGridLayout) ColorPanelGridLayout.getComponent(); } return null; } public void setColorPanelGridLayout(RichPanelGridLayout ColorPanelGridLayout) { this.ColorPanelGridLayout = ComponentReference.newUIComponentReference(ColorPanelGridLayout); } public void setColor(String color) { this.color = color; } public String getColor() { return color; } }
<af:resource type="javascript" source="/resources/js/menu-taskflow.js"/> <af:panelGridLayout id="pgl1" binding="#{pageFlowScope.menuBean.colorPanelGridLayout}" > <af:gridRow height="100%" id="gr1"> <af:gridCell width="100%" halign="stretch" valign="stretch" id="gc1" inlineStyle="background-color:#{pageFlowScope.menuBean.color};"> <af:selectOneRadio label="Color of your choosing #{pageFlowScope.menuBean.color}" id="colorRadio" clientComponent="true" styleClass="colorRadio"> <af:selectItem label="Red" value="red" id="si1"/> <af:selectItem label="Yellow" value="yellow" id="si2"/> <af:selectItem label="Blue" value="blue" id="si3"/> <af:serverListener type="menuColorSelectionEvent" method="#{pageFlowScope.menuBean.handleColorSelection}"/> </af:selectOneRadio> </af:gridCell> </af:gridRow> </af:panelGridLayout>
function informServerAboutColorSelection(color) { // get hold of the component that contains the serverListener - the select one radio // get hold of ADF Faces Client Side AdfRichSelectOneRadio object // we use a trick that assumes only one element is rendered in the entire page with a css style class colorRadio // (that also means that page fragment can be included only once and so can the taskflow that this fragment is included in; // for this simple example, that is an acceptable limitation) var htmlElementForRadio = document.getElementsByClassName("colorRadio"); // from the HTML element we get the element id and use that as the input for the findComponentByAbsoluteId call that returns the actual ADF Faces AdfRichSelectOneRadio object var radio = AdfPage.PAGE.findComponentByAbsoluteId(htmlElementForRadio[0].id); AdfCustomEvent.queue(radio, "menuColorSelectionEvent", { "newColor" : color }, true); }
The complete code is available from GitHub: https://github.com/lucasjellema/ADFClientSideEventBus.