2013-12-13

Programmatic full-reset of adf input components contained in af:switcher

Task: Reset each and every input component on a page after some action took place.

Solution: First of all requery the data that is used inside the ui input components.

Then access the Faces Context and set the ViewRoot to a newly created UiView. This can be found in the utility Java Class JSFUtils provided by Duncan Mills and Steve Muench. As an excerpt:

    public static final void refreshCurrentPage() {
        FacesContext context = getFacesContext();
        String currentView = getRootViewId();
        ViewHandler vh = context.getApplication().getViewHandler();
        UIViewRoot x = vh.createView(context, currentView);
        x.setViewId(currentView);
        context.setViewRoot(x);
    }


Issue: This does not seem to refresh components, that are dynamically generated inside an af:switcher. After recursive logging of the components that are refreshed, it seems to be that the org.apache.myfaces.trinidad.component.UIXSwitcher children are not accessed.

Solution 2: I assume that internally the "refreshCurrentPage" uses the same functionality, that is used by the getChildren() method derived by the javax.faces.component.UIComponent class. Unfortunetaly this method returns null for the UIXSwitcher component. Therefore you should use the getFacetsAndChildren() method (which works for the UIXSwitcher since there are only facet subnodes) and write your own refresh code that could look something like this:

    private void resetValueInputItems(AdfFacesContext adfFacesContext,
                                      UIComponent component) {
                     
        Iterator<UIComponent> items = component.getFacetsAndChildren();
        while(items.hasNext()){
           
            UIComponent item = items.next();
           
            resetValueInputItems(adfFacesContext, item);

            if (item instanceof RichInputText) {
                RichInputText input = (RichInputText)item;
                if (!input.isDisabled()) {
                    input.resetValue();
                    adfFacesContext.addPartialTarget(input);
                }
            } else if (item instanceof RichInputDate) {
                RichInputDate input = (RichInputDate)item;
                if (!input.isDisabled()) {
                    input.resetValue();
                    adfFacesContext.addPartialTarget(input);
                }
            } else if (item instanceof RichSelectOneChoice){
                RichSelectOneChoice lov = (RichSelectOneChoice) item;
                if (!lov.isDisabled()) {
                    lov.resetValue();
                    adfFacesContext.addPartialTarget(lov);
                }
            }
        }
        AdfFacesContext.getCurrentInstance().addPartialTarget(component);
    }


Result: Each component resets its Value, even those that are contained inside a af:switcher component.