Conditionally display row using JSF Datatable

后端 未结 6 1275
無奈伤痛
無奈伤痛 2021-02-19 07:16

I have some JSF code that currently works (as shown below), and I need to modify it to conditionally suppress the display of certain rows of the table. I know how to conditional

6条回答
  •  终归单人心
    2021-02-19 08:00

    I extend HtmlTableRenderer default renderer and overwrite renderRowStart method to achieve this by giving style attribute into table->tr element with value display:none.

    The item inside binding list needs to implement TableRow interface which only has one method of isHide. In the concrete class you can put any logic you like to give a boolean value.

    BTW, in this custom renderer also has PrimeFaces implementation like function which gives the message when table is empty and the table->tr will automatically calculate how many columns in the table and give proper value to colspan attribute.

    public class MyDataTableRenderer extends HtmlTableRenderer {
        private static final Integer[] ZERO_INT_ARRAY = new Integer[] { 0 };
        private static final String NO_RESULT_MESSAGE_ATTR_NAME = "noResultMessage";
        private static final String defaultEmptyMessage = "No records found";
        private static final Logger log = Logger.getLogger(DHSDataTableRenderer.class.getName());
    
    @Override
    public void encodeInnerHtml(FacesContext facesContext, UIComponent component) throws IOException {
        UIData uiData = (UIData) component;
        String message = (String) uiData.getAttributes().get(NO_RESULT_MESSAGE_ATTR_NAME);
        if (message == null || "".equals(message.trim())) {
            message = defaultEmptyMessage;
        }
    
        ResponseWriter writer = facesContext.getResponseWriter();
    
        int rowCount = uiData.getRowCount();
    
        int newspaperColumns = getNewspaperColumns(component);
    
        int columnNumber = getChildCount(component);
    
        if (rowCount == -1 && newspaperColumns == 1) {
            encodeInnerHtmlUnknownRowCount(facesContext, component);
            return;
        }
    
        if (rowCount == 0) {
            // nothing to render, to get valid xhtml we render an empty dummy
            // row
            writer.startElement(HTML.TBODY_ELEM, uiData);
            writer.writeAttribute(HTML.ID_ATTR, component.getClientId(facesContext) + ":tbody_element", null);
            writer.startElement(HTML.TR_ELEM, uiData);
            writer.startElement(HTML.TD_ELEM, uiData);
            writer.writeAttribute(HTML.COLSPAN_ATTR, columnNumber, null);
            writer.writeAttribute(HTML.CLASS_ATTR, "dhs-empty-table", null);
            writer.write(message);
            writer.endElement(HTML.TD_ELEM);
            writer.endElement(HTML.TR_ELEM);
            writer.endElement(HTML.TBODY_ELEM);
            return;
        }
    
        // begin the table
        // get the CSS styles
        Styles styles = getStyles(uiData);
    
        int first = uiData.getFirst();
        int rows = uiData.getRows();
        int last;
    
        if (rows <= 0) {
            last = rowCount;
        } else {
            last = first + rows;
            if (last > rowCount) {
                last = rowCount;
            }
        }
    
        int newspaperRows;
        if ((last - first) % newspaperColumns == 0) {
            newspaperRows = (last - first) / newspaperColumns;
        } else {
            newspaperRows = ((last - first) / newspaperColumns) + 1;
        }
        boolean newspaperHorizontalOrientation = isNewspaperHorizontalOrientation(component);
    
        // get the row indizes for which a new TBODY element should be created
        Integer[] bodyrows = getBodyRows(facesContext, component);
        int bodyrowsCount = 0;
    
        // walk through the newspaper rows
        for (int nr = 0; nr < newspaperRows; nr++) {
            boolean rowStartRendered = false;
            // walk through the newspaper columns
            for (int nc = 0; nc < newspaperColumns; nc++) {
    
                // the current row in the 'real' table
                int currentRow;
                if (newspaperHorizontalOrientation) {
                    currentRow = nr * newspaperColumns + nc + first;
                } else {
                    currentRow = nc * newspaperRows + nr + first;
                }
    
                // if this row is not to be rendered
                if (currentRow >= last) {
                    continue;
                }
    
                // bail if any row does not exist
                uiData.setRowIndex(currentRow);
                if (!uiData.isRowAvailable()) {
                    log.severe("Row is not available. Rowindex = " + currentRow);
                    break;
                }
    
                if (nc == 0) {
                    // first column in table, start new row
                    beforeRow(facesContext, uiData);
    
                    // is the current row listed in the bodyrows attribute
                    if (ArrayUtils.contains(bodyrows, currentRow)) {
                        // close any preopened TBODY element first
                        if (bodyrowsCount != 0) {
                            HtmlRendererUtils.writePrettyLineSeparator(facesContext);
                            writer.endElement(HTML.TBODY_ELEM);
                        }
                        HtmlRendererUtils.writePrettyLineSeparator(facesContext);
                        writer.startElement(HTML.TBODY_ELEM, uiData);
                        // Do not attach bodyrowsCount to the first TBODY
                        // element, because of backward compatibility
                        writer.writeAttribute(HTML.ID_ATTR, component.getClientId(facesContext) + ":tbody_element" + (bodyrowsCount == 0 ? "" : bodyrowsCount),
                                null);
                        bodyrowsCount++;
                    }
    
                    HtmlRendererUtils.writePrettyLineSeparator(facesContext);
                    renderRowStart(facesContext, writer, uiData, styles, nr);
                    rowStartRendered = true;
                }
    
                List children = null;
                for (int j = 0, size = getChildCount(component); j < size; j++) {
                    if (children == null) {
                        children = getChildren(component);
                    }
                    UIComponent child = children.get(j);
                    if (child.isRendered()) {
                        boolean columnRendering = child instanceof UIColumn;
    
                        if (columnRendering) {
                            beforeColumn(facesContext, uiData, j);
                        }
    
                        encodeColumnChild(facesContext, writer, uiData, child, styles, nc * uiData.getChildCount() + j);
    
                        if (columnRendering) {
                            afterColumn(facesContext, uiData, j);
                        }
                    }
                }
    
                if (hasNewspaperTableSpacer(uiData)) {
                    // draw the spacer facet
                    if (nc < newspaperColumns - 1) {
                        renderSpacerCell(facesContext, writer, uiData);
                    }
                }
            }
            if (rowStartRendered) {
                renderRowEnd(facesContext, writer, uiData);
                afterRow(facesContext, uiData);
            }
        }
    
        if (bodyrowsCount != 0) {
            // close the last TBODY element
            HtmlRendererUtils.writePrettyLineSeparator(facesContext);
            writer.endElement(HTML.TBODY_ELEM);
        }
    }
    
    @Override
    protected void renderRowStart(FacesContext facesContext, ResponseWriter writer, UIData uiData, Styles styles, int rowStyleIndex) throws IOException {
        writer.startElement(HTML.TR_ELEM, null); // uiData);
    
        renderRowStyle(facesContext, writer, uiData, styles, rowStyleIndex);
        Object obj = uiData.getRowData();
        boolean isHide = false;
        if (obj instanceof TableRow) {
            isHide = ((TableRow) obj).isHide();
        }
        if (isHide) {
            writer.writeAttribute("style", "display: none;", null);
        }
        Object rowId = uiData.getAttributes().get(org.apache.myfaces.shared.renderkit.JSFAttr.ROW_ID);
    
        if (rowId != null) {
            writer.writeAttribute(HTML.ID_ATTR, rowId.toString(), null);
        }
    }
    
    private void encodeInnerHtmlUnknownRowCount(FacesContext facesContext, UIComponent component) throws IOException {
        UIData uiData = (UIData) component;
        ResponseWriter writer = facesContext.getResponseWriter();
    
        Styles styles = getStyles(uiData);
    
        Integer[] bodyrows = getBodyRows(facesContext, component);
        int bodyrowsCount = 0;
    
        int first = uiData.getFirst();
        int rows = uiData.getRows();
        int currentRow = first;
        boolean isRowRendered = false;
    
        while (true) {
            uiData.setRowIndex(currentRow);
            if (!uiData.isRowAvailable()) {
                break;
            }
    
            isRowRendered = true;
    
            // first column in table, start new row
            beforeRow(facesContext, uiData);
    
            // is the current row listed in the bodyrows attribute
            if (ArrayUtils.contains(bodyrows, currentRow)) {
                // close any preopened TBODY element first
                if (bodyrowsCount != 0) {
                    HtmlRendererUtils.writePrettyLineSeparator(facesContext);
                    writer.endElement(HTML.TBODY_ELEM);
                }
                HtmlRendererUtils.writePrettyLineSeparator(facesContext);
                writer.startElement(HTML.TBODY_ELEM, uiData);
                // Do not attach bodyrowsCount to the first TBODY element,
                // because of backward compatibility
                writer.writeAttribute(HTML.ID_ATTR, component.getClientId(facesContext) + ":tbody_element" + (bodyrowsCount == 0 ? "" : bodyrowsCount), null);
                bodyrowsCount++;
            }
    
            HtmlRendererUtils.writePrettyLineSeparator(facesContext);
            renderRowStart(facesContext, writer, uiData, styles, currentRow);
    
            List children = null;
            for (int j = 0, size = getChildCount(component); j < size; j++) {
                if (children == null) {
                    children = getChildren(component);
                }
                UIComponent child = children.get(j);
                if (child.isRendered()) {
                    boolean columnRendering = child instanceof UIColumn;
    
                    if (columnRendering) {
                        beforeColumn(facesContext, uiData, j);
                    }
    
                    encodeColumnChild(facesContext, writer, uiData, child, styles, j);
    
                    if (columnRendering) {
                        afterColumn(facesContext, uiData, j);
                    }
                }
            }
    
            renderRowEnd(facesContext, writer, uiData);
            afterRow(facesContext, uiData);
    
            currentRow++;
    
            if (rows > 0 && currentRow - first > rows) {
                break;
            }
        }
    
        if (!isRowRendered) {
            // nothing to render, to get valid xhtml we render an empty dummy
            // row
            writer.startElement(HTML.TBODY_ELEM, uiData);
            writer.writeAttribute(HTML.ID_ATTR, component.getClientId(facesContext) + ":tbody_element", null);
            writer.startElement(HTML.TR_ELEM, uiData);
            writer.startElement(HTML.TD_ELEM, uiData);
            writer.endElement(HTML.TD_ELEM);
            writer.endElement(HTML.TR_ELEM);
            writer.endElement(HTML.TBODY_ELEM);
            return;
        }
    
        if (bodyrowsCount != 0) {
            // close the last TBODY element
            HtmlRendererUtils.writePrettyLineSeparator(facesContext);
            writer.endElement(HTML.TBODY_ELEM);
        }
    }
    
    private Integer[] getBodyRows(FacesContext facesContext, UIComponent component) {
        Integer[] bodyrows = null;
        String bodyrowsAttr = (String) component.getAttributes().get(JSFAttr.BODYROWS_ATTR);
        if (bodyrowsAttr != null && !"".equals(bodyrowsAttr)) {
            String[] bodyrowsString = StringUtils.trim(StringUtils.splitShortString(bodyrowsAttr, ','));
            // parsing with no exception handling, because of JSF-spec:
            // "If present, this must be a comma separated list of integers."
            bodyrows = new Integer[bodyrowsString.length];
            for (int i = 0; i < bodyrowsString.length; i++) {
                bodyrows[i] = new Integer(bodyrowsString[i]);
            }
    
        } else {
            bodyrows = ZERO_INT_ARRAY;
        }
        return bodyrows;
    }
    

    }

提交回复
热议问题