Primefaces <f:selectitems>属性设置了多次,有或没有值</f:selectitems>

时间:2013-11-05 02:03:01

标签: jsf primefaces

我整天都调试了一个问题。我还是想不出来。基本上,我使用数据表可扩展功能为每一行显示一些额外的选项。用户可以检查一些或不检查,然后用户单击更新按钮更新数据库。所以一行会有很多选择。

<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>

Managed Bean:

setSelectedTabsNames(List 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);
}

}

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

删除嵌套的“表单”,但仍无效。我发现问题不会影响数据表的最后一行。假设我在数据表中有三行,多次调用setter并在上次操作前两行时设置为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.
        }
    }

}

2 个答案:

答案 0 :(得分:1)

触发ajax事件时,将发送表单中的所有输入元素。这意味着将发送所有selectManyCheckbox(每行一个)。这就是多次调用setSelectedTabsNames的原因。

您必须更改设计实施的方式。一种方法是将所选选项存储在FopsUser对象中,这样您就可以value="#{user.selectedTabsNames}"

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

这样,每行的选定选项卡将单独存储。

答案 1 :(得分: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"/>