JSF选择菜单,处理删除的值

时间:2015-02-07 12:08:29

标签: jsf-2.2 selectonemenu

在我们的应用程序中,我们有各种选择字段。 select字段的内容始终使用数据库中的值填充,例如currency选择器将包含数据库中添加的货币,或User可能会根据某些用户的角色选择对象。

现在,问题是此数据可能会随着时间的推移而发生变化,但使用此值的实例应保持不变。如果某个用户现在已被选为leadDeveloper,由于他的角色,但他离开了公司,则选择列表不再包含该用户,因此选择字段现在将显示无选择选项,因为列表源不再包含该元素。

有没有一种好方法可以绕过这个问题?

具体例子:

的java:

@Named
@ViewScoped
public class MyBean{

  public List<IKeyValuePair> getAvailableDeveloper(){
      // everything available to select-fields is implementing
      // iKeyValuePair, most the time used as id/name, depending on entity
      return userDataService.getUsersWithRole("developer");
  } 
}

public class User implements IKeyValuePair{

    //properties

    @Override
    public string getKey(){
       //use id
       return this.id.toString();
    }

    @Override
    public string getValue(){
       //use lastname, firstname
       return this.lastname + ", " + this.firstname;
    }
}

XHTML:

<p:selectOneMenu value="#{project.leadDeveloper}" style="width:125px" readonly="#{project.closed}">
      <f:selectItem itemLabel="Select One" itemValue="" />
      <f:selectItems value="#{myBean.availableDevelopers}" var="dev" 
          itemLabel="#{dev.getValue()}" itemValue="#{dev.getKey()}" />
 </p:selectOneMenu>

现在,用户将从该列表中选择 - 让我们说 alice 。从现在开始,该项目的历史视图将在项目结束后将 alice 显示为已禁用的selectOneMenu中的选定开发人员。

2年后,alice离开了公司,因此她的角色开发人员已被撤销。 getAvailableDeveloper()将不再包含alice,因此所选值不再是数据源的一部分 - 现在,选择字段将显示选择一个

我可以手动确保将相关用户添加到列表中以用于历史记录(如果缺少) - 但是这需要我在相应的getter中实现 case-by-case -method,取决于实体类型。

如果可以在selectOneMenu的(自定义)渲染器内以自动方式处理它会更好。但在我这样做之前,我想询问是否有关于这个主题的最佳实践解决方案。

ps:代码不是精确的副本,只是一个概述问题的快速示例。

1 个答案:

答案 0 :(得分:0)

我终于通过代理方法调用每个人getter来解决它,该代理方法负责剩下的工作。

而不是

public List<IKeyValuePair> getAvailableDeveloper(){
  // everything available to select-fields is implementing
  // iKeyValuePair, most the time used as id/name, depending on entity
  return userDataService.getUsersWithRole("developer");
} 

以及标记

<f:selectItems value="#{myBean.availableDevelopers}" var="dev" 
      itemLabel="#{dev.getValue()}" itemValue="#{dev.getKey()}" />

我最终调用了一个“通用”方法,传递当前选择和实际List,最后将此选择添加到返回列表中,如果不存在:

<f:selectItems value="#{myBean.proxyForLists(myBean.availableDevelopers, currentElement)}" var="dev" 
      itemLabel="#{dev.getValue()}" itemValue="#{dev.getKey()}" />

和代理方法

 public List<IKeyValuePair> proxyForLists(List<IKeyValuePair> source, Object selection){

   if (selection == null) return source;

   if (selection instanceof User){
       User selectedUser = (User) selection;
       KeyValuePair kvp = new KeyValuePair(selectedUser.getShortName(), selectedUser);
       if (!source.contains(kvp)){
          source.add(kvp);
       }
    }
    //other types handled as well. 
    return source;
 }

因此,只要选定的值A不再是源列表的一部分,就会通过代理方法添加它,使选择字段能够再次显示它。对于“新”创作,A不再是源列表的一部分,因此用户无法再选择A