ADF Faces Client Side Event Bus - Use ServerListener to engage Server from Consuming Fragment for programmatic Partial Refresh image 7

ADF Faces Client Side Event Bus – Use ServerListener to engage Server from Consuming Fragment for programmatic Partial Refresh

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.

image

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).

image

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.

image

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:

image

 

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;
        }
    }
    
    
  • The PanelGridLayout component in the menu.jsff page has a binding attribute that links it to the managed bean ; this makes the partial refresh possible.
  • The selectOneRadio component has a serverListener component that links it to a method in the menuBean.
  • <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>
    
  • A JavaScript function informServerAboutColorSelection() has been added to send the custom event to the serverListener and thereby effectively to the managed bean; this function is invoked from the existing function handleColorSelection() that is called by the client side event bus when the color selection event takes place.

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.