How to hide/show a row in a panelgrid based on data entered in another row

你说的曾经没有我的故事 提交于 2019-12-12 04:20:37

问题


I have a panelGrid with a row containing a selectCheckBoxMenu and another row which should be shown or hidden based on the selection.

Updating the entire panel when the selection is changed is not desired, because the selectCheckBoxMenu would be refreshed and the user would have to open the dropdown again for each item he wants to select.

Updating the controls to be hidden or shown can't solve the problem either because they can't be updated if they are not shown because rendered was false before.

So, I wrapped these controls in a Fragment and update those fragments. Functionally that's OK, but now I have an ugly layout because in most situations the controls will be hidden and a small empty row is shown.

Is it possible to get rid of that ugly empty row without breaking the functionality again?

My xhtml looks like this:

<p:panelGrid id="panel" columns="2" border="0" cellpadding="5"
    cellspacing="2">
    ...
    <h:outputLabel value="Type" />
    <p:selectCheckboxMenu id="deviceTypeMenu" value="#{controller.criteria.dts}" label="All" converter="dtConverter"
          filter="true" filterMatchMode="contains"
          panelStyle="width:300px" valueChangeListener="#{controller.onChange}"
          updateLabel="true">
        <p:ajax update="sclabel scfield" />
        <f:selectItems value="#{deviceTypeBean.alldts}" var="dt"
            itemLabel="#{dt.name}" itemValue="#{dt}"/>
    </p:selectCheckboxMenu>
    ...
    <p:fragment id="sclabel">
        <h:outputText value="Detail" rendered="#{controller.detailRequired}"/>
    </p:fragment>
    <p:fragment id="scfield">
        <p:selectCheckboxMenu rendered="#{controller.detailRequired}" converter="#{detailConverter}"
            value="#{controller.criteria.detail}" label="All details"
            filter="true" filterMatchMode="contains"
            style="width:300px;" scrollHeight="100"
            updateLabel="true">
            <f:selectItems value="#{detailConverter.values}" var="adetail"
                itemLabel="#{adetail.name}" itemValue="#{adetail}" />
        </p:selectCheckboxMenu>
    </p:fragment>
    ...
</p:panelGrid>

回答1:


Cause

The empty row contains padding. The table row and table cell html elements are created by the panelgrid because it renders those for every row and as soon as there some child element a row is rendered. And they have styleclasses on them which are set by the panelgrid and refer to styles which contain padding. The fragments, even if they don't render anything themselves are enough to trigger that.

Remark: We are using the Modena theme from Primefaces. So, the padding is part of the Modena theme. Extract of the Modena stylesheet which causes the problem:

.ui-panelgrid .ui-panelgrid-cell {
    border-width: 1px;
    border-style: solid;
    border-color: inherit;
    padding: 4px 10px;
}

Solution

I did the following changes:

  1. I explicitly specified rows and columns using primefaces row and column components and added a style class "ui-panelgrid-cell-nopadding" to the columns of the row which I need to hide. I added the style below to my stylesheet so that, that style class removes/overrides padding from that cell which was added by the panelgrid.

    .ui-panelgrid .ui-panelgrid-cell-nopadding { padding: 0px 0px; }

  2. I added a div around the controls in the cells and applied the class ui-panelgrid-cell to it to add the padding which I removed from the cells.

    Remark: I tried a panel first for this, but then it became more complicated because the Primefaces panel also adds styleclasses which caused inconsistent layout with the other rows in my panelgrid (fontsize was changed).

  3. I added a second fragment between the fragments I already had and the div's and I moved the rendered attribute from the controls inside the cells to these fragments. So that the padding defined on the div is no longer there if I don't want the row to be rendered.

    One fragment is not enough anymore, because I needed one with an id to be able to update it via ajax and a second with the rendered attribute. If you put those attributes on the same fragment, you can't make it visible anymore as soon as it's hidden. Moving the id's to the explicitly defined columns is also not possible because then these cells behave strangely probably because they are empty when rendering the panelgrid initially. When the cells were updated to make them visible, the content of both the cells of my row appeared in the left cell and the right cell remained empty.

  4. After that, I had a border around the div's because that is specified in the Modena style which I applied to the div's to have the padding that I removed from the cells. And because the content of the div's was smaller than the cell, I had an extra border, I didn't want. So I added something to my stylesheet to remove that border.

    .ui-panelgrid .ui-panelgrid-cell-nopadding .ui-panelgrid-cell { border:none; border:0px; }

My xhtml now looks like this:

<p:panelGrid id="panel" border="0">
    ...
    <p:row>
        <p:column>
            <h:outputLabel value="Type" />
            <p:selectCheckboxMenu id="deviceTypeMenu" value="#{controller.criteria.dts}" label="All" converter="dtConverter"
        </p:column>
        <p:column>
                filter="true" filterMatchMode="contains"
                panelStyle="width:300px" valueChangeListener="#{controller.onChange}"
                updateLabel="true">
                <p:ajax update="sclabel scfield" />
                <f:selectItems value="#{deviceTypeBean.alldts}" var="dt"
                    itemLabel="#{dt.name}" itemValue="#{dt}"/>
            </p:selectCheckboxMenu>
        </p:column>
    </p:row>
    ...
    <p:row>
        <p:column styleClass="ui-panelgrid-cell-nopadding">
            <p:fragment id="sclabel">
                <p:fragment rendered="#{controller.detailRequired}">
                    <div class="ui-panelgrid-cell">
                        <h:outputText value="Detail"/>
                    </div>
                </p:fragment>
            </p:fragment>
        </p:column>
        <p:column styleClass="ui-panelgrid-cell-nopadding">
            <p:fragment id="scfield">
                <p:fragment rendered="#{controller.detailRequired}">
                    <div class="ui-panelgrid-cell">
                        <p:selectCheckboxMenu converter="#{detailConverter}"
                            value="#{controller.criteria.detail}" label="All details"
                            filter="true" filterMatchMode="contains"
                            style="width:300px;" scrollHeight="100"
                            updateLabel="true">
                            <f:selectItems value="#{detailConverter.values}" var="adetail"
                                itemLabel="#{adetail.name}" itemValue="#{adetail}" />
                        </p:selectCheckboxMenu>
                    </div>
                </p:fragment>
            </p:fragment>
        </p:column>
    <.p:row>
    ...
</p:panelGrid>



回答2:


For example put an Id to row:

in javascript : if (condition that you need) { document.getElementById("form:idEmpresa").style.display = "none";
}

Ready



来源:https://stackoverflow.com/questions/45084457/how-to-hide-show-a-row-in-a-panelgrid-based-on-data-entered-in-another-row

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!