0

编辑:2017-04-28 这里描述了完全相同的问题(不同的情况/应用程序):Process f:viewParam only on page load


Primefaces 6.1.RC2

JSF 莫哈拉 2.3.0


我已经有一个基于 Java backing-bean 的解决方法(如下所述),用于解决以下p:dataTable原因的问题,但我对这种解决方法不太满意,我想p:dataTable更好地理解行编辑的行为,如果可能的话我会想为我的问题找到一个纯 XHTML 级别的解决方案。(顺便说一句,我在其他方面非常有经验p:dataTable,多年来我已经将其用于一些非常复杂的应用程序。)

这与 中的错误或错误无关p:dataTable,但它在行编辑期间的行为方式在一种情况下给我带来了问题。

以下代码示例完全简化并适用于本论坛。

我有一个实体元素,它有一个关系List<Link> getLinks(),其中链接也是一个实体。

Element 有一个编辑器edit.xhtml

目的是拥有一个links_editor.xhtml可以嵌入到edit.xhtml.

有一个符合 CDI 的@ViewScoped @Named支持 bean Manager

edit.xhtml 依赖于f:viewParam加载一个元素进行编辑:

<f:view>
    <f:metadata>
       <f:viewParam name="id" value="#{manager.id}"/>
    </f:metadata>
</f:view>

在支持 bean 中的位置Manager

public void setId(Long id) {
    if (id != null) {
      //load an Element from database for editing by id

并且在links_editor.xhtml

<cc:implementation>
    <div id="#{cc.clientId}">

                <p:growl id="testgrowl"/>

                <p:dataTable
                    id="links_table"
                    editable="true"                    
                    var="link"
                    value="#{cc.attrs.element.links}"
                    >   

                    <p:ajax 
                        event="rowEdit" 
                        listener="#{cc.attrs.manager.onLinkRowEdit}"
                        update="#{cc.clientId}:testgrowl"
                        />

                    <p:column headerText="Link title">
                        <p:cellEditor>
                            <f:facet name="output">
                                <h:outputText value="#{link.name}" />
                            </f:facet>
                            <f:facet name="input">
                                <p:inputText id="name" value="#{link.name}"/>
                            </f:facet>
                        </p:cellEditor>                        
                    </p:column>

                    <p:column headerText="Link URL">
                        <p:cellEditor>
                            <f:facet name="output">
                                <h:outputText value="#{link.urlAsString}" />
                            </f:facet>
                            <f:facet name="input">
                                <p:inputText id="url" value="#{link.urlAsString}"/>
                                <p:message 
                                    for="url" 
                                    display="icon"                                        
                                    />
                            </f:facet>
                        </p:cellEditor>                        
                    </p:column>
                    <p:column>
                        <p:rowEditor />
                    </p:column>                    
                </p:dataTable>

行编辑监听器:

public void onLinkRowEdit(RowEditEvent event) {
    Link link = (Link) event.getObject();
    try {
        checkLink(link); //throws if URL string malformed         
        JsfUtil.addInfoMessage("DEBUG: Link: "+link);
    } catch (LocalUpdateException ex) {
        JsfUtil.addErrorMessage(ex.getMessage());
    }
}

JsfUtil显然只是利用FacesContext.getCurrentInstance().addMessage(...)

问题/担忧:

p:dataTable 如果我第一次编辑 Link 行,然后使用“tick save”,onLinkRowEdit则调用侦听器,但诊断显示该值似乎没有改变。原因是它f:viewParam被调用:

       <f:viewParam name="id" value="#{manager.id}"/>

这(通过未详细显示的路由)Element再次从数据库加载实体 via setId(Long id),因此在复合组件中edit_links.xthml这实质上会重置#{cc.attrs.element.links},因此任何更改都将被丢弃。

有趣的是,如果(不重新加载整个@ViewScoped 页面)第二次编辑未调用的同一p:dataTable行,然后它会按需要工作。f:viewParam

一种解决方法(相当骇人听闻)是“阻止”任何在视图范围支持 bean 中通过 id 重新加载 Element 的尝试Manager

public void setId(Long id) {

   //HACK/WORKAROUND: prevent reload of Element by id
   if (Objects.equals(id, this.id)) {
       return;
   }

    if (id != null) {
      //load an Element from database for editing by id

需要明确的是,我知道在支持 bean 中的 JSF 下频繁访问的信息的获取器中使用 @PostConstruct 和/或惰性数据库获取的常用策略。而且我不想在这里f:viewParam完全放弃这种方法(并且它适用于同样使用相同 Manager bean 的其他情况)。

我特别感兴趣的是 Primefaces p:dataTable

Q1:当行信息(在这种情况下)显然已经可用时,为什么p:dataTable需要在第一行编辑期间调用然后“勾选保存”?f:viewParamelement.links

Q2:为什么不需要在第二行编辑期间p:dataTable调用然后“勾选保存”?f:viewParam

Q3:是否有一种基于 JSF XHTML 的方法来防止在 rowEdit 然后“勾选保存”(包括第一次)期间p:dataTable调用?f:viewParam


更新:2017-04-21:现在有一个适用于 NetBeans 8.2 的迷你测试 Web 应用程序,在以下位置演示了该问题:

https://github.com/webelcomau/Webel_PrimeFaces_test_p50445_dataTable_fviewParam

下载主 ZIP 存档,解压缩,然后在 NetBeans IDE 8.2 中打开它。您不需要 Git 克隆项目。确保将 Glassfish-4.1.1 设置为项目的服务器。

那里的自述文件和网络应用程序测试页面本身都提供了重现问题(或与我有关的行为)的精确步骤。

我已经投入了一些精力来分析这个,因为我p:dataTable在编辑表单中使用了很多“嵌入” f:viewParam,并且我想更好地理解这个问题,即使它不是一个实际的问题p:dataTable

4

0 回答 0