【问题标题】:How to get row index of currently validating row in p:dataTable?如何获取 p:dataTable 中当前验证行的行索引?
【发布时间】:2019-07-07 12:03:48
【问题描述】:

我正在使用 cellEditors 为用户的 IP 范围创建一个 p:dataTable,其中包含 p:inputMask。数据表由 2 个可编辑列组成。 要验证我必须:

  1. 检查指定的ip地址是否匹配RegEx,
  2. 确保范围的开始实际上早于结束,
  3. 确保指定范围不与之前输入的范围相交。

前两部分没有太大的噪音。 第三个要求我检查指定的范围是在先前输入的范围之前还是之后。您只需检查开始和结束是否在每个其他 IP 范围之前或之后。简单吧?

验证周期。

    for (Groupip gip : searchResults) {
        long ipend = ipToLong(InetAddress.getByName(gip.getIpend()));
        long ipstart = ipToLong(InetAddress.getByName(gip.getIpstart()));
        boolean validLeft = true, validRight = true;
        validLeft = validLeft && ipstart < ipValidated;
        validLeft = validLeft && ipend < ipValidated;
        validLeft = validLeft && ipstart < ipValidating;
        validLeft = validLeft && ipend < ipValidating;
        validRight = validRight && ipstart > ipValidated;
        validRight = validRight && ipend > ipValidated;
        validRight = validRight && ipstart > ipValidating;
        validRight = validRight && ipend > ipValidating;
        if (validLeft || validRight) {
            //OK
        } else {
            //ERROR
        }
    }

数据表。

    <p:dataTable id="ips1" widgetVar="ips1" var="ip" value="#{groupipController.searchResults}" editable="true"
                 rowKey="#{ip.groupcode}-#{ip.ipstart}-#{ip.ipend}" selection="#{groupipController.selected}" selectionMode="single"
                 >
        <f:facet name="header">
            Диапазон IP
        </f:facet>
        <p:ajax event="rowEditCancel" listener="#{groupipController.onRowCancel}" />
        <p:ajax event="rowEditInit" listener="#{groupipController.onRowEditInit}" />
        <p:ajax event="rowEdit" listener="#{groupipController.onRowEdit}" update=":form:msgs :form:ips1 :form:growlmsgs" process=":form:ips1"/>

        <p:column headerText="От" style="min-height: 16px" id='from_col'>
            <p:cellEditor>
                <f:facet name="output"><h:outputText value="#{ip.ipstart}" /></f:facet>
                <f:facet name="input">
                    <p:inputMask mask="999.999.999.999" value="#{ip.ipstart}" id="fromip" autoClear="false" slotChar="0"
                                 validator="#{groupipController.validate}"
                                 class="ui-inputfield ui-inputmask ui-widget ui-state-default ui-corner-all p-0-1 w-100 h-100"/>
                </f:facet>
            </p:cellEditor>
        </p:column>
        <p:column headerText="До" style="min-height: 16px" id='to_col'>
            <p:cellEditor>
                <f:facet name="output"><h:outputText value="#{ip.ipend}" /></f:facet>
                <f:facet name="input">
                    <p:inputMask mask="999.999.999.999" value="#{ip.ipend}" id="toip" autoClear="false" slotChar="0"
                                 validator="#{groupipController.validate}"
                                 class="ui-inputfield ui-inputmask ui-widget ui-state-default ui-corner-all p-0-1 w-100 h-100"/>  
                </f:facet>
            </p:cellEditor>
        </p:column>
        <p:column width="10%" >
            <p:rowEditor rendered="#{armgroupController.update}" />
        </p:column>
    </p:dataTable>

但还有更多。 searchResults 是一个变量,它是 dataTable 的源,其中包含 List&lt;Groupip&gt;。但它也包含当前正在编辑的行。所以我必须排除它,否则我将无法通过验证,将范围与自身进行比较。

我该怎么做呢?我可以找到编辑行的行索引的唯一方法是使用以下代码获取 cliendId 的最后一个值(在浏览器中看起来像这样:form:ips1:2:toip):

if (gip == searchResults.get(Integer.parseInt(component.getClientId().split(":")[2]))) {
    continue;
}

这是不合适的,因为命名容器可能会改变。 那么,我想知道,还有其他方法可以获取行索引吗?

【问题讨论】:

    标签: validation jsf primefaces datatable


    【解决方案1】:

    您当前组件的 id 始终是完整 clientID 列表中的最后一个,并且您自己声明取最后一个值,但实际上您取的是第三个值(索引 2)

    如果您实际上将最后一个索引(base-0)作为行索引,那么您(大多数情况下)总是没问题。

    String[] fields = component.getClientId().split(":");
    int index = Integer.parseInt(fields[fields.length-2]); 
    if (gip == searchResults.get(index)) {
        continue;
    }
    

    如果有人将此“当前”组件包装在命名容器中,则索引将不是最后一个而是最后一个,而是在此之前,甚至在此之前。因此,您可以在循环中添加它以获取拆分 clientId 的第一部分,即数字,因为 JSF (html) id's cannot start with a number 因此不能是数字,因此您是“安全的”。

    String[] fields = component.getClientId().split(":");
    int indexPos = fields.length-2;
    int index = -1;
    do {
       try {
           index = Integer.parseInt(fields[indexPos]); 
       } catch {
           indexPos--;
       }
    } while (index == -1)
    if (gip == searchResults.get(index)) {
        continue;
    }
    

    您也可以尝试将组件的父级转换为 Datatable 并查看它是否包含可以使用的 getCurrentRow() 之类的内容,但是您还应该创建一个循环来获取父级的父级,如果父级不是数据表。

    一个要调查的例子是http://showcase.omnifaces.org/validators/validateUniqueColumn的来源

    【讨论】:

    • 你确定我总是可以解析 cliendID 吗?我真的不确定,想要更多的解释。或者更好的是,一种无需 clientId 即可获取 rowIndex 的方法
    • 稍微修改一下答案。
    猜你喜欢
    • 1970-01-01
    • 2019-04-09
    • 2021-11-12
    • 1970-01-01
    • 2021-10-13
    • 2016-10-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-16
    相关资源
    最近更新 更多