每次我在dataTable中单击commandButton时都会重新创建ViewScoped bean

时间:2012-02-29 13:57:31

标签: jsf-2 datatable primefaces managed-bean

我正在使用primefaces 3.1.1版,Mojarra 2.1.3,Netbeans 7.0.1,Glassfish Server 3.1。

我的测试应用程序正在使用具有顶部,左侧,内容,右侧和底部布局的facelet模板以及原始div和css。用户使用容器管理的jdbcrealm登录后,将显示使用该模板的主index.html。

我在左侧面板上放置了一个导航菜单,随后在点击menuitem时用ajax更新中心面板内容。中心面板将使用sessionScoped <ui:include>NavigationBean中动态更新。

在其中一个页面clientList.xhtml中,我添加了<p:dataTable>按钮,通过弹出<p:dialog>来查看详细信息。我使用viewCoped bean来保存dataTable上显示的数据列表。

问题是,当我单击按钮在每行的最后一列中选择一行时,对话框根本不显示,并且我的p:ajaxStatus gif图像一直无休止地滚动。当我用netbeans调试程序时,我注意到再次调用构造函数,单击按钮后前一个实例就消失了。

这是我的index.xhtml使用facelets模板。

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:p="http://primefaces.org/ui"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:c="http://java.sun.com/jsp/jstl/core">
<ui:composition template="/BySalesAutomationTemplate.xhtml">
    <ui:define name="title">
        <h:outputText value="Facelet Index Page"></h:outputText>
    </ui:define>
    <ui:define name="top">
        TOP
    </ui:define>
    <ui:define name="left">
        <ui:include src="users/menu#{request.isUserInRole('ADMIN') ? 'Admin' : 'User'}.xhtml" />
    </ui:define>
    <ui:define name="right">
        <h:outputText value="Cuba2 daan"></h:outputText>
    </ui:define>
    <ui:define name="maincontent">
        <c:if test="#{navigationBean.page!=null}">
            <ui:include src="#{navigationBean.page}.xhtml" />
        </c:if>
    </ui:define> 
    <ui:define name="bottom">
        <center>2012</center> 
    </ui:define>
  </ui:composition>
</html>

这是clientList.xhtml页面,点击左侧面板菜单上的链接,显示在index.xhtml的中心面板中。

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:p="http://primefaces.org/ui"
  xmlns:f="http://java.sun.com/jsf/core">
<h:head>
    <title>Client Listing</title>
</h:head>
<h:body>
    <p>Client List</p>
    <h:form>
        <h:commandButton action="#{authBackingBean.logout}" value="Logout" />
    </h:form>
    <f:view>
        <h:form id="formdetail" prependId="false">
            <p:ajaxStatus>
                <f:facet name="start">
                    <h:graphicImage value="images/loading.gif" />
                </f:facet>
                <f:facet name="complete">
                    <h:outputText value="" />
                </f:facet>
            </p:ajaxStatus>
            <p:growl id="growl" showDetail="true"/>
            <p:dataTable id="dtClientList" value="#{saClientController.lazyModel}" rowsPerPageTemplate="10,20,30,50" 
                         paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}" 
                         paginatorAlwaysVisible="false" var="item" paginator="true" rows="10">
                <f:facet name="header">
                    <h:outputText value="Client List"/>
                </f:facet>
                <p:column filterBy="#{item.idSaClient}">
                    <f:facet name="header">
                        <h:outputText value="IdSaClient"/>
                    </f:facet>
                    <p:commandLink action="#{saClientController.showDetails(item)}" value="#{item.idSaClient}" target=":maincontent"/>                        
                </p:column>
                <p:column filterBy="#{item.saClientName}">
                    <f:facet name="header">
                        <h:outputText value="saClientName"/>
                    </f:facet>
                    <h:outputText value="#{item.saClientName}"/>
                </p:column>
                <p:column filterBy="#{#item.saClientAddress}">
                    <f:facet name="header">
                        <h:outputText value="SaClientAddress"/>
                    </f:facet>
                    <h:outputText value="#{item.saClientAddress}"/>
                </p:column>
                <p:column style="width:40px">  
                    <h:panelGrid columns="3" styleClass="actions" cellpadding="2">  
                        <p:commandButton id="selectButton" update=":formdetail:display" oncomplete="clientDialog.show()" icon="ui-icon-search" title="View">                                  
                            <f:setPropertyActionListener value="#{item}" target="#{saClientController.selectedSaClient}" />  
                        </p:commandButton>  
                    </h:panelGrid>  
                </p:column>  
                <f:facet name="footer">
                    <h:outputText value="Client List"/>
                </f:facet>
            </p:dataTable>                      
        </h:form>

        <p:dialog id="clientDialog" header="Client Detail" widgetVar="clientDialog" resizable="false" showEffect="explode" hideEffect="explode">
            <h:panelGrid id="display" columns="2" cellpadding="4"> 
                 <f:facet name="header"> 
                     <h:outputText value="Selected Row" />
                 </f:facet> 
                 <h:outputText value="ID" />
                 <h:outputText value="#{saClientcontroller.selectedSaClient.idSaClient}" />
                 <h:outputText value="NAME:" /> 
                 <h:outputText value="#{saClientcontroller.selectedSaClient.saClientName}" /> 
                 <h:outputText value="DESCRIPTION:" />  
                 <h:outputText value="#{saClientcontroller.selectedSaClient.saClientAddress}" />  
             </h:panelGrid>
        </p:dialog>                   

    </f:view>
  </h:body>
</html>

这是我的Backing Bean。

public class SaClientController implements Serializable {

    @EJB
    private SaClientFacade saClientFacade;
    private SaClient selectedSaClient;
    private LazyDataModel<SaClient> lazyModel;
    private List<SaClient> saclients;

    /** Creates a new instance of SaClientController */
    public SaClientController() {
    }

    @PostConstruct
    public void Init() {
        saclients = saClientFacade.Retrieve();
        lazyModel = new LazyDataModelImp(saclients);
    }

    public LazyDataModel<SaClient> getLazyModel() {
        return lazyModel;
    }

    public List<SaClient> getClients() {
        return saClientFacade.Retrieve();
    }

    public SaClient getDetails() {
        return selectedSaClient;
    }

    public String showDetails(SaClient selectedSaClient) {
        this.selectedSaClient = selectedSaClient;
        return "DETAILS";
    }

    public String update() {
        System.out.println("###UPDATE###");
        selectedSaClient = saClientFacade.Update(selectedSaClient);
        return "SAVED";
    }

    public String list() {
        System.out.println("###LIST###");
        return "LIST";
    }

    public SaClient getSelectedSaClient() {
        return selectedSaClient;
    }

    public void setSelectedSaClient(SaClient selectedSaClient) {
        this.selectedSaClient = selectedSaClient;
    }

    public String dummyAction()
    {
        return null;
    }
}

这是LazyModelImp

public class LazyDataModelImp extends LazyDataModel<SaClient> {

    private List <SaClient> datasource;

    public LazyDataModelImp(List<SaClient> datasource) {
        this.datasource = datasource;
    }

    @Override
    public SaClient getRowData(String rowKey) {
        for (SaClient saclient : datasource) {
            if (saclient.getIdSaClient().toString().equals(rowKey)) {
                return saclient;
            }
        }
        return null;
    }

    @Override
    public Object getRowKey(SaClient saclient) {
        return saclient.getIdSaClient().toString();
    }

    @Override
    public List<SaClient> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters) {
        List<SaClient> data = new ArrayList<SaClient>();
        //filter        
        for (SaClient saclient : datasource) {
            boolean match = true;
            for (Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
                try {                    
                    String filterProperty = it.next();
                    String filterValue = filters.get(filterProperty);
                    String fieldValue = String.valueOf(saclient.getFilterSortFieldValue(filterProperty));
                    if (filterValue == null || fieldValue.startsWith(filterValue.toUpperCase()) || fieldValue.startsWith(filterValue.toLowerCase())) {
                        match = true;
                    } else {
                        match = false;
                        break;
                    }
                } catch (Exception e) {
                    match = false;
                }
            }
            if (match) {
                data.add(saclient);
            }
        }
        //rowCount
        int dataSize = data.size();
        this.setRowCount(dataSize);
        //paginate
        if (dataSize > pageSize) {
            try {
                return data.subList(first, first + pageSize);
            } catch (IndexOutOfBoundsException e) {
               return data.subList(first, first + (dataSize % pageSize));
            }
        }
        else {
            return data;
        }
        //sort
        //if (sortField != null) {
        //    Collections.sort(data, new LazySorter(sortField, sortOrder));
        //}       
        //return data;
    }
}

我已经在web.xml中禁用了部分状态保存。

<context-param> 
    <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name> 
    <param-value>false</param-value> 
</context-param> 

第一次单击clienList.xhtml中dataTable的最后一列中的视图详细信息commandButton时,backingBean将重新初始化。并且对话框根本不显示。但按F5后。可以显示对话框但没有任何内容,对话框中显示的唯一内容是标签outputText但不是bean值,它们是空的。对不起新手问题。如果有人能告诉我做错了什么,我可能会非常高兴,也许会对导航以及我在index.xhtml中显示所有内容的策略提出一些建议(所以我一直只有1个视图ID { {1}},对吧?)是对的。

1 个答案:

答案 0 :(得分:0)

这可能是您的PrimeFaces对话框的问题,h:form周围有p:dialog。我注意到当表单元素的子项时,PrimeFaces对话框无法正常工作。

尝试将此对话框表单放在对话框的内容中。

<p:dialog id="clientDialog" header="Client Detail" widgetVar="clientDialog" resizable="false" showEffect="explode" hideEffect="explode">
  <h:form id="formdialog" prependId="false">
    <h:panelGrid id="display" columns="2" cellpadding="4">
    ...