[richfaces-issues] [JBoss JIRA] (RF-9443) switchable panels: It should be possible to iterate child panels using a4j:repeat component

Brian Leathem (JIRA) jira-events at lists.jboss.org
Fri Sep 21 10:16:37 EDT 2012


    [ https://issues.jboss.org/browse/RF-9443?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12720673#comment-12720673 ] 

Brian Leathem commented on RF-9443:
-----------------------------------

By far the simplest way to get this working for columns is to have the iterator use the visitor pattern to walk the children of the a4j:repeat.  A naive implementation of this idea is as follows:

{code:title="DataTableColumnsIterator modified to walk UIRepeat"}

class DataTableColumnsIterator extends AbstractIterator<UIComponent> {

    class VisitState {
        int index = 0;
        int repeaterIndex = -1;
        UIComponent repeater;
        UIComponent component;
        boolean valid = false;

        public void trackRepeater(UIComponent repeater) {
            repeaterIndex = index;
            this.repeater = repeater;
            valid = true;
        }

        public void forgetRepeater() {
            repeaterIndex = -1;
            repeater = null;
            valid = false;
        }
    }

    private Iterator<UIComponent> childrenIterator;
    private VisitState visitState;
    private FacesContext context;

    public DataTableColumnsIterator(UIComponent component) {
        super();
        visitState = new VisitState();
        this.childrenIterator = component.getChildren().iterator();
        context = FacesContext.getCurrentInstance();
    }

    @Override
    protected UIComponent computeNext() {
        while (childrenIterator.hasNext() || visitState.repeater != null) {
            UIComponent child = visitState.repeater == null ? childrenIterator.next() : visitState.repeater;

            if (child instanceof UIColumn || child instanceof Column) {
                visitState.index++;
                return child;
            }
            else if (child instanceof UIRepeat) {
                final UIRepeat repeater = (UIRepeat) child;
                if (! visitState.valid) {
                    visitState.trackRepeater(repeater);
                }
                try {
                    DataVisitor visitor = new DataVisitor() {
                        public DataVisitResult process(FacesContext context, Object rowKey, Object argument) {
                            repeater.setRowKey(context, rowKey);
                            if (repeater.isRowAvailable()) {
                                if (repeater.getChildCount() > 0) {
                                    visitState.repeater = repeater;
                                    int index = visitState.repeaterIndex + 1;
                                    for (UIComponent child : repeater.getChildren()) {
                                        if (index == visitState.index + 1) {
                                            visitState.index++;
                                            visitState.component = child;
                                            return DataVisitResult.STOP;
                                        }
                                        index++;
                                    }
                                    visitState.forgetRepeater();
                                }
                            }
                            return DataVisitResult.CONTINUE;
                        }
                    };

                    repeater.walk(context, visitor, null);
                } finally {
                    repeater.setRowKey(context, null);
                }
                if (visitState.component != null) {
                    UIComponent component = visitState.component;
                    visitState.component = null;
                    return component;
                }
            }
        }
        return endOfData();
    }
}
{code}

the problem with the above approach, is the visit context is closed when the column object is returned.  This means any attributes to be resolved that rely on the _rowKey_ (such as the _clientId_) will fail.

One way around this, is to have the above iterator keep the visit context alive until the iteration over the UIRepeat's children is complete.  Further investigation is required.
                
> switchable panels: It should be possible to iterate child panels using a4j:repeat component
> -------------------------------------------------------------------------------------------
>
>                 Key: RF-9443
>                 URL: https://issues.jboss.org/browse/RF-9443
>             Project: RichFaces
>          Issue Type: Bug
>      Security Level: Public(Everyone can see) 
>          Components: component-panels-layout-themes
>    Affects Versions: 4.0.0.Milestone2
>            Reporter: Ilya Shaikovsky
>            Assignee: Brian Leathem
>             Fix For: 4.3.0.Milestone2
>
>
> requirement present there - http://community.jboss.org/wiki/RichFaces4xswitchablepanels
> Alex, consider this issue to implementation only after all the new components tasks for M4. If will not fit - postpone to next one as it has workaround.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira


More information about the richfaces-issues mailing list