OmniFaces的Ajax工具的updateColumn()没有更新p:dataTable

3

最近,我的一个关于OmniFaces Ajax.updateColumn()的问题在以下链接得到了解答:

如何使用OmniFaces Ajax.updateColumn()或Ajax.updateRow()通过p:ajax

在那个情况下,dataTable是JSF标准的h:dataTable,效果很好。

现在,在这种情况下,我试图在enduser通过存在于p:dataTable之外的p:calendar组件选择日期时更新PrimeFaces p:dataTable。p:dataTable的xhtml如下:

<p:dataTable id="flightDataTable" var="flight" 
             value="#{pf_flightController.flightsForOrder}">

    <p:column headerText="Airport" style="text-align: center !important;">
        <p:inputText value="#{flight.airportTx}" maxlength="25" size="10" label="Airport"/>
    </p:column>

    <p:column headerText="Airline" style="text-align: center !important;">
        <p:inputText value="#{flight.airlineTx}" maxlength="25" size="10" label="Airline"/>
    </p:column>

    <p:column headerText="Flight Number" style="text-align: center !important;">
        <p:inputText value="#{flight.flightNumber}" maxlength="8" size="10" label="Flight Number"/>
    </p:column>

    <p:column headerText="Type" style="text-align: center !important;">
        <h:selectOneMenu value="#{flight.flightType}" label="Flight Type">
            <f:selectItem itemValue="#{bundle.DropdownOptionValueArrive}" itemLabel="#{bundle.DropdownOptionLabelArrive}"/>
            <f:selectItem itemValue="#{bundle.DropdownOptionValueDepart}" itemLabel="#{bundle.DropdownOptionLabelDepart}"/>
        </h:selectOneMenu>
    </p:column>

    <p:column headerText="Date" style="text-align: center !important;">
        <h:panelGroup rendered="#{pf_usersController.loggedInViaAndroid == 'N'}">
            <p:calendar value="#{flight.flightDate}" navigator="true"
                        label="Flight Date"
                        pattern="MM/dd/yyyy" size="10">
                <f:convertDateTime pattern="MM/dd/yyyy" />
            </p:calendar>
        </h:panelGroup>
        <h:panelGroup rendered="#{pf_usersController.loggedInViaAndroid == 'Y'}">
            <p:inputText value="#{flight.flightDate}"
                         label="Flight Date" type="date">
                <f:convertDateTime pattern="yyyy-MM-dd" />
            </p:inputText>
        </h:panelGroup>
    </p:column>

    <p:column headerText="Time" style="text-align: center !important;">
        <h:panelGroup rendered="#{pf_usersController.loggedInViaAndroid == 'N'}">
            <pe:timePicker value="#{flight.flightTime}"
                           label="Flight Time" mode="popup"
                           showPeriod="true" style="width: 80px;">
                <f:convertDateTime pattern="hh:mm a" />
            </pe:timePicker>
        </h:panelGroup>
        <h:panelGroup rendered="#{pf_usersController.loggedInViaAndroid == 'Y'}">
            <p:inputText value="#{flight.flightTime}"
                         label="Flight Time" type="time">
                <f:convertDateTime pattern="HH:mm" />
            </p:inputText>
        </h:panelGroup>
    </p:column>

</p:dataTable>

在生产环境中,p:calendar p:ajax update="..." 更新了整个航班p:dataTable,因此p:dataTable中的日期列被成功更新。我知道,如果它没有出现问题,就不要修复它,但今天我正在修改这段代码和xhtml,所以我想使用OmniFaces Ajax实用程序的updateColumn()来仅更新此PrimeFaces p:dataTable的所有行的'一个'列。

下面是当最终用户通过p:calendar选择日期时执行的代码片段; 这是调用OmniFaces Ajax实用程序的updateColumn()的代码。

private void updateFlightDateOnAdd() {
    flightController.updateFlightDateOnAdd(current.getTripDateTime());

    UIData flightsDataTable = null;
    try {
        flightsDataTable = (UIData) Components.findComponent(":orderAddForm:flightDataTable");
    } catch (Exception e) {
        System.out.println("pf_OrdersController.updateFlightDateOnAdd(): caught exception on Components.findComponent(...)");
    }
    if (flightsDataTable != null) {
        System.out.println("pf_OrdersController.updateFlightDateOnAdd(): Components.findComponent(...) found " + flightsDataTable.getClientId());
        Ajax.updateColumn(flightsDataTable, 4);
    }
    else {
        System.out.println("pf_OrdersController.updateFlightDateOnAdd(): Components.findComponent(...) returned null");
    }
}

以下是POJO(普通Java对象)的定义:
public class FlightForOrder {
    private Integer flightId;
    private String airportTx, airlineTx, flightNumber;
    private Character flightType;
    private Date flightDate, flightTime;

    public FlightForOrder() {

    }

    public Integer getFlightId() {
        return flightId;
    }

    public void setFlightId(Integer flightId) {
        this.flightId = flightId;
    }

    public String getAirportTx() {
        return airportTx;
    }

    public void setAirportTx(String airportTx) {
        this.airportTx = airportTx;
    }

    public String getAirlineTx() {
        return airlineTx;
    }

    public void setAirlineTx(String airlineTx) {
        this.airlineTx = airlineTx;
    }

    public Date getFlightDate() {
        return flightDate;
    }

    public void setFlightDate(Date flightDate) {
        this.flightDate = flightDate;
    }

    public String getFlightNumber() {
        return flightNumber;
    }

    public void setFlightNumber(String flightNumber) {
        this.flightNumber = flightNumber;
    }

    public Date getFlightTime() {
        return flightTime;
    }

    public void setFlightTime(Date flightTime) {
        this.flightTime = flightTime;
    }

    public Character getFlightType() {
        return flightType;
    }

    public void setFlightType(Character flightType) {
        this.flightType = flightType;
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 97 * hash + Objects.hashCode(this.flightId);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final FlightForOrder other = (FlightForOrder) obj;
        if (!Objects.equals(this.flightId, other.flightId)) {
            return false;
        }
        return true;
    }

}

在测试过程中,服务器日志中出现了以下内容:

INFO: pf_OrdersController.updateFlightDateOnAdd(): Components.findComponent(...) found orderAddForm:flightDataTable

因此,这意味着我获得了PrimeFaces p:dataTable的良好参考,所以我将类型为UIData的组件传递给Ajax.updateColumn()。
最终结果是,OmniFaces Ajax实用程序的updateColumn()未更新PrimeFaces dataTable。
我只是注释掉了Ajax.updateColumn(...),并重新添加了update="..."到p:calendar p:ajax,然后PrimeFaces dataTable成功更新。
请建议我需要做什么来确保通过Ajax.updateColumn(...)更新PrimeFaces dataTable。谢谢。
1个回答

1

替换

<p:column headerText="Date" style="text-align: center !important;">
    <h:panelGroup rendered="#{pf_usersController.loggedInViaAndroid == 'N'}">
        <p:calendar value="#{flight.flightDate}" navigator="true"
                    label="Flight Date"
                    pattern="MM/dd/yyyy" size="10">
            <f:convertDateTime pattern="MM/dd/yyyy" />
        </p:calendar>
    </h:panelGroup>
    <h:panelGroup rendered="#{pf_usersController.loggedInViaAndroid == 'Y'}">
        <p:inputText value="#{flight.flightDate}"
                     label="Flight Date" type="date">
            <f:convertDateTime pattern="yyyy-MM-dd" />
        </p:inputText>
    </h:panelGroup>
</p:column>

<p:column headerText="Date" style="text-align: center !important;">
    <p:calendar value="#{flight.flightDate}" navigator="true"
                label="Flight Date"
                pattern="MM/dd/yyyy" size="10"
                rendered="#{pf_usersController.loggedInViaAndroid == 'N'}">
        <f:convertDateTime pattern="MM/dd/yyyy" />
    </p:calendar>
    <p:inputText value="#{flight.flightDate}"
                 label="Flight Date" type="date"
                 rendered="#{pf_usersController.loggedInViaAndroid == 'Y'}">
        <f:convertDateTime pattern="yyyy-MM-dd" />
    </p:inputText>
</p:column>

应该修复它。

解释:Ajax#updateColumn() 仅将直接子元素的客户端 ID 添加到 PartialViewContext#getRenderIds() 中。然而,一个没有任何应该出现在结果 HTML 输出中的属性(例如 id)的 <h:panelGroup> 不会渲染任何内容到 HTML 输出中。因此,JS/Ajax 无法定位 <h:panelGroup> 的 HTML 表示以便更新它。

修复方法是将表格单元格的具体内容作为直接子元素,这样 JS/Ajax 就能够定位并替换它们。另一种选择是给这些面板组一个具体的 id,但在这个结构中这是不必要的。


像往常一样,你是对的,BalusC!我从你这里学到了更多东西,并在实践中不断学习。在这种类型的xhtml中,我时而使用h:panelGroup,有时则不使用h:panelGroup。有时,我只需将rendered="..."添加到组件中,有时则需要在h:panelGroup rendered="..."中包装多个组件。感谢你的答案、解释和OmniFaces! - Howard
还有一件事,这个 Ajax.updateColumn() 的性能比 p:ajax update="..." 更好。当我将 dataTable 包含在 p:ajax update="..." 中时,所有列都失去了当前值,除了日期列。为什么?好问题,但是 OmniFaces 通过 Ajax 实用程序的 updateColumn() 来解决了它! - Howard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接