Conditionally display row using JSF Datatable

后端 未结 6 1298
無奈伤痛
無奈伤痛 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 07:53

    Use the empty css selector as suggested here, but with tr instead of td. This worked for me.

    https://stackoverflow.com/a/19177424

    As described here: https://developer.mozilla.org/en-US/docs/Web/CSS/:empty This selector works on all current browsers.

    <style>
      tr:empty {
        display: none;
      }
    </style>
    
    0 讨论(0)
  • 2021-02-19 07:58

    extension to Brian's solution. To display the column names I did the following in primefaces

    <p:dataTable value="#{eiBean.dce.ilDbConns}" var="c">
        <p:columnGroup type="header">
            <p:row>
                <p:column colspan="1" />
                <p:column colspan="1" />
            </p:row>
            <p:row>
                <p:column headerText="DataBase Type" width="auto" />
                <p:column headerText="URL" width="400" />
            </p:row>
        </p:columnGroup>
        <p:column rendered='#{c.conType == "TARGET"}'>
            <p:outputLabel value="#{c.dbType}" />
        </p:column>
        <p:column rendered='#{c.conType == "TARGET"}'>
            <p:outputLabel value="#{c.dbUrl}" />
        </p:column>         
    </p:dataTable>
    
    0 讨论(0)
  • 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<UIComponent> 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<UIComponent> 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;
    }
    

    }

    0 讨论(0)
  • 2021-02-19 08:04

    For people using richFaces, you can use rich:column's filterExpression attribute.

    <rich:column filterExpression="#{put your expression here}">
        ...
    </rich>
    

    If the condition is not met, the complete row is filtered out.

    Example is using seam EL!

    0 讨论(0)
  • 2021-02-19 08:05

    Rows correspond to data objects in the collection of your table. If you don't want the row, don't put the object in the collection.

    Alternatively, you can use the rowClasses parameter for dataTable.

    Bean code:

    public String getRowClasses() {
        StringBuilder sb = new StringBuilder();
        for (Data data : myData) {
            sb.append(data.hide ? 'hide,' : 'show,');
        }
        return sb.toString();
    }
    

    CSS:

    tr.hide {display:none;}
    
    0 讨论(0)
  • 2021-02-19 08:09

    I've successfully hidden rows by putting a rendered attribute in all the <h:column> tags. The problem is that it suppresses the table headers. If your table has no table headers (they are <f:facet name="header"> tags embedded in the <h:column>), this approach might work for you.

    I ended up using multiple lists in the backing bean, as I needed the table headers.

    0 讨论(0)
提交回复
热议问题