如何根据在另一行中输入的数据隐藏/显示面板网格中的一行 [英] How to hide/show a row in a panelgrid based on data entered in another row

查看:73
本文介绍了如何根据在另一行中输入的数据隐藏/显示面板网格中的一行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 panelGrid,其中一行包含 selectCheckBoxMenu,另一行应根据选择显示或隐藏.

不希望在更改选择时更新整个面板,因为 selectCheckBoxMenu 将被刷新,并且用户必须为他想要选择的每个项目再次打开下拉列表.

更新隐藏或显示的控件也不能解决问题,因为如果之前render为false而未显示,则无法更新.

因此,我将这些控件包装在一个 Fragment 中并更新这些 Fragment.功能上没问题,但现在我有一个丑陋的布局,因为在大多数情况下,控件将被隐藏并显示一个小的空行.

是否有可能在不再次破坏功能的情况下摆脱那个丑陋的空行?

我的 xhtml 看起来像这样:

<p:panelGrid id="panel" columns="2" border="0" cellpadding="5"单元格间距=2">...<h:outputLabel value="类型"/><p:selectCheckboxMenu id="deviceTypeMenu" value="#{controller.criteria.dts}" label="All" converter="dtConverter"filter="true" filterMatchMode="包含"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" render="#{controller.detailRequired}"/></p:fragment><p:fragment id="scfield"><p:selectCheckboxMenu 渲染="#{controller.detailRequired}" converter="#{detailConverter}"value="#{controller.criteria.detail}" label="所有细节"filter="true" filterMatchMode="包含"样式=宽度:300像素;"滚动高度=100"updateLabel="true"><f:selectItems value="#{detailConverter.values}" var="detail"itemLabel="#{adetail.name}" itemValue="#{adetail}"/></p:selectCheckboxMenu></p:fragment>...</p:panelGrid>

解决方案

原因

空行包含填充.表格行和表格单元格 html 元素由 panelgrid 创建,因为它会为每一行呈现这些元素,并且只要有某个子元素呈现一行.并且它们有样式类,它们由面板网格设置并引用包含填充的样式.这些片段,即使它们自己不渲染任何东西,也足以触发它.

备注:我们使用的是 Primefaces 的 Modena 主题.因此,填充是摩德纳主题的一部分.导致问题的 Modena 样式表的摘录:

.ui-panelgrid .ui-panelgrid-cell {边框宽度:1px;边框样式:实心;边框颜色:继承;填充:4px 10px;}

解决方案

我做了以下更改:

  1. 我使用 primefaces 行和列组件明确指定了行和列,并向需要隐藏的行的列添加了样式类ui-panelgrid-cell-nopadding".我将下面的样式添加到我的样式表中,以便该样式类从面板网格添加的单元格中删除/覆盖填充.

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

  2. 我在单元格中的控件周围添加了一个 div,并将类 ui-panelgrid-cell 应用于它以添加我从单元格中删除的填充.

    备注:我首先为此尝试了一个面板,但后来变得更加复杂,因为 Primefaces 面板还添加了样式类,这导致我的面板网格中的其他行布局不一致(字体大小已更改).

  3. 我在已有的片段和 div 之间添加了第二个片段,并将渲染属性从单元格内的控件移动到这些片段.因此,如果我不希望呈现该行,则 div 上定义的填充不再存在.

    一个片段已经不够了,因为我需要一个带有 id 的片段,以便能够通过 ajax 更新它,第二个片段带有渲染属性.如果你把这些属性放在同一个片段上,你就不能在它隐藏后立即让它可见.将 id 移动到显式定义的列也是不可能的,因为这些单元格的行为可能很奇怪,因为它们在最初渲染面板网格时是空的.当单元格更新为可见时,我所在行的两个单元格的内容都出现在左侧单元格中,而右侧单元格保持为空.

  4. 在那之后,我在 div 周围有一个边框,因为这是在 Modena 样式中指定的,我将其应用于 div 以具有我从单元格中删除的填充.因为 div 的内容比单元格小,所以我有一个额外的边框,我不想要.因此,我在样式表中添加了一些内容以删除该边框.

    .ui-panelgrid .ui-panelgrid-cell-nopadding .ui-panelgrid-cell {边界:无;边框:0px;}

我的 xhtml 现在看起来像这样:

...<p:row><p:列><h:outputLabel value="类型"/><p:selectCheckboxMenu id="deviceTypeMenu" value="#{controller.criteria.dts}" label="All" converter="dtConverter"</p:列><p:列>filter="true" filterMatchMode="包含"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:列></p:row>...<p:row><p:column styleClass="ui-panelgrid-cell-nopadding"><p:fragment id="sclabel"><p:fragment render="#{controller.detailRequired}"><div class="ui-panelgrid-cell"><h:outputText value="详细信息"/>

</p:fragment></p:fragment></p:列><p:column styleClass="ui-panelgrid-cell-nopadding"><p:fragment id="scfield"><p:fragment render="#{controller.detailRequired}"><div class="ui-panelgrid-cell"><p:selectCheckboxMenu 转换器="#{detailConverter}"value="#{controller.criteria.detail}" label="所有细节"filter="true" filterMatchMode="包含"样式=宽度:300像素;"滚动高度=100"updateLabel="true"><f:selectItems value="#{detailConverter.values}" var="detail"itemLabel="#{adetail.name}" itemValue="#{adetail}"/></p:selectCheckboxMenu>

</p:fragment></p:fragment></p:列><.p:row>...</p:panelGrid>

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>

解决方案

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>

这篇关于如何根据在另一行中输入的数据隐藏/显示面板网格中的一行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆