2013-11-05 63 views
0

我有一個調試半天的問題。我仍然無法弄清楚。基本上,我使用數據表展開功能爲每行顯示一些額外的選項。用戶可以檢查一些或沒有他們,然後用戶點擊更新按鈕來更新數據庫。所以一排會有很多選擇。Primefaces <f:selectItems>屬性被設置了幾次,有或沒有值

<f:selectItems value="#{adminBean.allTabNames}" />是利用收集用戶的選擇的選項,然後管理bean將它們保存到數據庫中,一旦用戶點擊更新。

那麼問題是,public void setSelectedTabsNames(List<String> selectedTabsNames) { this.selectedTabsNames = selectedTabsNames; }方法被調用幾次與預期值或空值(空單)。值是隨機傳遞的,有時沒有值。

查看:

<ui:composition xmlns="http://www.w3.org/1999/xhtml" 
xmlns:f="http://java.sun.com/jsf/core" 
xmlns:h="http://java.sun.com/jsf/html" 
xmlns:ui="http://java.sun.com/jsf/facelets" 
xmlns:p="http://primefaces.org/ui"> 
<h:form id="form1"> 
    <p:growl id="growl" showDetail="true"/> 

    <p:dataTable var="user" value="#{adminBean.users}" scrollable="false" 
     > 

     <p:ajax event="rowToggle" listener="#{adminBean.onRowToggle(user.id)}" update=":form:tabView:form1:growl" /> 

     <f:facet name="header"> 
      All Users 
     </f:facet> 

     <p:column style="width:2%"> 
      <p:rowToggler /> 
     </p:column> 

     <p:column headerText="First Name"> 
      <h:outputText value="#{user.firstname}" /> 
     </p:column> 

     <p:column headerText="Last Name"> 
      <h:outputText value="#{user.lastname}" /> 
     </p:column> 

     <p:column headerText="Password"> 
      <h:outputText value="#{user.password}" /> 
     </p:column> 

     <p:column headerText="Active"> 
      <h:outputText value="#{user.active}" /> 
     </p:column> 

     <p:column headerText="Last Login"> 
      <h:outputText value="#{user.timestamp}" /> 
     </p:column> 

     <p:column headerText="Notes"> 
      <h:outputText value="#{user.notes}" /> 
     </p:column> 

     <p:rowExpansion> 
      <h:panelGrid id="display" columns="1" cellpadding="4"> 

       <h:outputText value="Tabs: " /> 
       <p:selectManyCheckbox id="grid" value="#{adminBean.selectedTabsNames}" 
        layout="pageDirection" > 
        **<f:selectItems value="#{adminBean.allTabNames}" />** 
       </p:selectManyCheckbox> 
      </h:panelGrid> 

      <br/> 

      <p:commandButton value="Update" id="submit" actionListener="#{adminBean.updateTabsForUser(user.id)}" ajax="true" /> 

     </p:rowExpansion> 

    </p:dataTable> 

</h:form> 

託管Bean:

setSelectedTabsNames(名單selectedTabsNames)

package org.userlogin.view; 

import java.io.Serializable; 
import java.util.List; 

import javax.faces.bean.ManagedBean; 
import javax.faces.bean.SessionScoped; 
import javax.faces.bean.ViewScoped; 

import org.userlogin.db.entity.FopsUser; 
import org.userlogin.service.UserService; 

@ManagedBean 
@ViewScoped 
public class AdminBean implements Serializable { 

private static final long serialVersionUID = -9002632063713324598L; 

private List<FopsUser> users; 

private List<String> selectedTabsNames; 
private List<String> allTabNames; 

private UserService us; 

public AdminBean() { 
    us = new UserService(); 
    users = us.getAllUsers(); 
    allTabNames = us.getAllTabs(); 
} 

public List<FopsUser> getUsers() { 
    return users; 
} 

public void setUsers(List<FopsUser> users) { 
    this.users = users; 
} 

public void setSelectedTabsNames(List<String> selectedTabsNames) { 
    this.selectedTabsNames = selectedTabsNames; 
} 

public List<String> getSelectedTabsNames() { 
    return selectedTabsNames; 
} 

public List<String> getAllTabNames() { 
    return allTabNames; 
} 

public void setAllTabNames(List<String> allTabNames) { 
    this.allTabNames = allTabNames; 
} 

public void updateTabsForUser(Long uid) { 
    us.updateTabsUser(selectedTabsNames); 
} 

public void onRowToggle(Long uid) { 
    //set current selected user 
    us.setCurrent(uid); 
    this.selectedTabsNames = us.getTabNamesByUserId(uid); 
} 

}

--------- ------更新-------

刪除嵌套「形式」,但仍然沒有工作。我發現這個問題不影響數據表的最後一行。假設我在數據表中有三行,那麼當我操縱前兩行時,調用者被多次調用並在上次被設置爲null。但是對於最後一行,setter仍然被多次調用。最後一次調用設置預期值。現在,我只需添加

public void setSelectedOptions(List<String> selectedOptions) { 
    if (selectedOptions == null || selectedOptions.size() == 0) { 
     return; 
    } 
    this.selectedOptions = selectedOptions; 
} 

它仍然是醜陋...

------------更新----------

<p:selectManyCheckbox id="grid" value="#{user.selectedTabsNames}" 
    layout="pageDirection" > 
    **<f:selectItems value="#{adminBean.allTabNames}" />** 
</p:selectManyCheckbox> 

應該像這樣設計:將selectedTabsNames放入User對象。但仍然沒有工作。因爲我有這個AJAX提交按鈕,這就要求每個selectedTabsNames接到電話,在經過空列表。

<p:rowExpansion> 
<h:panelGrid id="display" columns="1" cellpadding="4"> 

    <h:outputText value="Tabs: " /> 
    <p:selectManyCheckbox id="grid" value="# {user.selectedTabsNames}" 
        layout="pageDirection" > 
     <f:selectItems value="#{adminBean.allTabNames}" /> 
    </p:selectManyCheckbox> 
    <p:commandButton value="Update" id="submit" ajax="true" />  
</h:panelGrid> 

<br/> 
</p:rowExpansion> 

用我自己的解決方案----------------更新(不優雅的,但作品)-----

每次AJAX BUTTOM已被點擊,整個數據表被更新。這意味着每個setSelectedItem方法將被調用期望值或空值。我不知道如何改變這一點。

所以修改我從AJAX按鈕調用下面的邏輯save()方法:

public void save(Long userId, List<String> selectedItem) { 
    for (User user: users) { 
     if (user.getId() == userId) { 
      //update selectedItem in db for this user. 
     } else { 
      // read selectedItems in db 
      // update selectedItem in user object. 
     } 
    } 

} 
+0

你確定你沒有使用n ested形式?你正在更新:form:tabView:form1:growl。 – 757071

+0

你需要閱讀:http://stackoverflow.com/q/2090033/1530938 – kolossus

+0

@johny是的,我使用嵌套的形式。我只是用google搜索了一下,我認爲使用嵌套表單是無效的。我會試着看看會發生什麼。 –

回答

1

當AJAX事件被觸發,其形式中的所有輸入元件被髮送。這意味着所有selectManyCheckbox(每行一個)都被髮送。這就是爲什麼setSelectedTabsNames被多次調用的原因。

你必須改變你設計實現的方式。一種方法woud是存儲在FopsUser對象選擇的選項,這樣你就可以做value="#{user.selectedTabsNames}"

<p:selectManyCheckbox id="grid" value="#{user.selectedTabsNames}" 
    layout="pageDirection" > 
    **<f:selectItems value="#{adminBean.allTabNames}" />** 
</p:selectManyCheckbox> 

這樣,每一行的選擇選項卡分開存放。

+0

好主意。我在這裏發現了一個類似的問題。 http://stackoverflow.com/questions/18131194/expanded-primefacess-datatables-rows-misbehavior –

+0

將selectedTabsNames放入每個用戶對象後,仍然存在問題。提交ajax按鈕請求後,將調用每個selectedTabsNames。 –

+0

所有selectedTabsNames方法仍然被調用。 –

0

我可能是錯的,但我不認爲rowToggle事件是一種可以處理行級參數的ajax事件。想想這樣:var="user"是一個行迭代級別的變量,可用於數據表中的每一行。另一方面,rowToggle事件是單級標記,適用於整個表作爲一個組件。因此,有可能是不適合的數據表就知道你指的是當您使用 adminBean.onRowToggle(user.id)哪一行的可靠方法,它只會選擇被渲染

弄個更有效的方式在最後一行這是用在支持Bean,你沒有ToggleEvent聽衆傳遞變量切換行的細節:

 public void onRowToggle(ToggleEvent te){ 
     User theSelectedUser = (User)te.getData(); 
     int id = theSelectedUser.getId(); 
     } 

在你看來,你現在將有:

<p:ajax event="rowToggle" listener="#{adminBean.onRowToggle}" update=":form:tabView:form1:growl"/>