JSF 2.0 和 selectManyListbox 中的生命周期问题

Posted

技术标签:

【中文标题】JSF 2.0 和 selectManyListbox 中的生命周期问题【英文标题】:Trouble with lifecycle in JSF 2.0 and selectManyListbox 【发布时间】:2012-03-12 13:43:21 【问题描述】:

我正在尝试制作一个简单的管理页面来管理用户列表。 jsf 代码如下所示:

 <h:selectOneMenu  id="selectUser" value="#adminBean.user_id" valueChangeListener="#adminBean.userSelected" >
                    <f:selectItems value="#adminBean.myModelUsersValues" />   
                    <a4j:ajax event="valueChange" render="login password privilege_list" execute="@this"/>      
                 </h:selectOneMenu > 

   <table>
      <tr>
        <td><h:outputLabel styleClass="LabelStyle" value="login: "/></td>         
      </tr>
      <tr>
        <td>
            <h:inputText id="login" value="#adminBean.login"/>
        </td>   
        <td>
        <h:message for="login" style="color:red"/>
        </td>                        
      </tr>
      <tr>
        <td><h:outputLabel styleClass="LabelStyle" value="password: "/></td>         
      </tr>
      <tr>
        <td>
            <h:inputText id="password" value="#adminBean.password"/>
        </td>   
        <td>
        <h:message for="password" style="color:red"/>
        </td>                      
      </tr>       
      <tr>
        <td><h:outputLabel styleClass="LabelStyle" value="privilege list: "/></td>         
      </tr>
      <tr>
        <td>
            <h:selectManyListbox  id="privilege_list" value="#adminBean.privilegeList">
                <f:selectItems value="#adminBean.privilegeValues" />                          
             </h:selectManyListbox > 
        </td>    
        <td>
        <h:message for="privilege_list" style="color:red"/>
        </td>                      
      </tr>
    </table>
    <br/>
    <h:commandButton id="addButton" value="Add" action="#adminBean.addUser" styleClass="ButtonStyle"/>               
    <h:commandButton id="deleteButton" value="Delete" action="#adminBean.deleteUser" styleClass="ButtonStyle"/>                  
    <h:commandButton id="clearButton" value="Clear" action="#adminBean.clear" styleClass="ButtonStyle"/>  

问题是当页面加载时,所有项目都是空的。现在,当我单击“添加”按钮时,我发现 valueChangeListener="#adminBean.userSelected" 运行,它将我的权限列表替换为第一个用户的权限列表。当我使用清除按钮时也是如此 - 所有字段都是空的,但是当我再次单击添加按钮时,列表是来自第一个用户的列表(并且只有列表 - 没有其他输入文本)。我尝试将immediate="true" 添加到添加按钮并解决了这个问题,但是当然,我输入输入文本的所有值都不会传递给adminBean.addUser 操作方法。我的 bean 是 viewscoped(由于 selectManyListBox 上的验证错误,我需要使用它)。这是 Java 代码(到目前为止,addUser 方法只发送一个记录器方法并检查 i login 是否存在,以及是否在 priv.list 上选择了某事):

@ManagedBean(name="adminBean")
@ViewScoped
public class AdminBean 
private String user_id ="";
private String login ="";
private String password ="";
private ArrayList<String> privilegeList = new ArrayList<String>();

private User model = new User();
private TreeMap<String, User> usersValuesBackendMap = new TreeMap<String, User>();
private TreeMap<String, String> privilegesValues = new TreeMap<String, String>();
private TreeMap<String, String> myModelUsersValues = new TreeMap<String, String>();

...

    @javax.annotation.PostConstruct
    public void init()
           

        usersValuesBackendMap = queryDAO.getAllUsers();

        for (Map.Entry<String, User> usr : usersValuesBackendMap.entrySet()) 
            myModelUsersValues.put(usr.getValue().getLogin(), usr.getKey() );
        

        privilegesValues = queryDAO.getFullPrivilegeList();
        user_id = ""; 
    
    public void userSelected(ValueChangeEvent event)
           String newValue = event.getNewValue().toString();       

           User user = usersValuesBackendMap.get(newValue);

           login = user.getLogin();
           password = user.getPassword();
           privilegesValues.clear();
           for (String privilege: user.getPrivilegeValues() )      
               privilegesValues.put(privilege, privilege);
           
       

        public String clear()

            user_id ="";
            login ="";
            password ="";
            privilegesValues = queryDAO.getFullPrivilegeList(); 
            return "";
        

有趣的是,我在 clearing 方法中添加了 immediate="true" ,然后……相反的情况 - 列表没问题,但 inputTexts 已填满。

【问题讨论】:

【参考方案1】:

一些事实:

    valueChangeListener!oldValue.equals(newValue) 时运行。 valueChangeListener 不是客户端事件侦听器。它完全是服务器端。 valueChangeListener 完全独立于它是 ajax 请求还是普通请求。它在所有类型的请求上调用,包括正常的表单提交。

你需要&lt;a4j:ajax listener&gt;

<h:selectOneMenu  id="selectUser" value="#adminBean.user_id">
    <f:selectItems value="#adminBean.myModelUsersValues" />   
    <a4j:ajax event="valueChange" listener="#adminBean.userSelected" render="login password privilege_list" execute="@this"/>      
</h:selectOneMenu > 

public void userSelected(AjaxBehaviorEvent event)
    User user = usersValuesBackendMap.get(user_id);
    // ...

【讨论】:

希望我仍然可以依靠一些帮助,因为它是同一个项目。你的建议有效,但我还有另一个问题。当我添加用户时,一切正常,我可以在 SelectOneMenu 中看到新用户。但是,当我删除它时,它仍然在列表中(尽管选择时没有填写任何字段)。当然,我更新 bean 方法中的列表与添加用户操作中的列表完全相同。可能是什么问题?我尝试将按钮切换到 a4j:ajax,但它是相同的(不发送消息)。

以上是关于JSF 2.0 和 selectManyListbox 中的生命周期问题的主要内容,如果未能解决你的问题,请参考以下文章

在同一个 Tomcat 服务器上部署 JSF 1.2 和 JSF 2.0 应用程序

RichFaces 3.3.3 和 JSF 2.0 工作示例

Tomcat 7、JSF 2.0 和 @PostConstruct

JSF 2.0 和 Facelets

使用 JSF 2.0 和 Primefaces 设置项目

带有 Eclipse 和 Tomcat 的 JSF 2.0 教程 [关闭]