JSF Select 菜单,处理删除的值

JSF Select Menu, handle removed values

在我们的应用程序中,我们有各种 select 字段。 select 字段的内容总是用数据库中的值填充,例如 currency select 或将包含添加到数据库中的货币,或者 User 对象可能根据特定用户的角色进行选择。

现在,问题是此数据可能会随着时间的推移而改变,但使用此值的 实例应该保持不变。如果用户现在因为他的角色而被纠察为 leadDeveloper,但他离开了公司,select-列表不再包含该用户,因此 select 字段现在将显示 no-select 选项,因为列表源不再包含该元素。

有什么好的方法可以绕过这个问题吗?

具体例子:

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。从现在开始,一旦项目结束,该项目的历史视图将在禁用的 selectOneMenu 中显示 alice 作为 selected 开发人员。

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

我可以手动确保将有问题的用户添加到列表中以供历史记录使用(如果丢失)——但是这将是我需要实施的事情个案 在相应的 getter 方法中,具体取决于实体类型。

如果这可以在 selectOneMenu 的(自定义)渲染器中以自动方式处理,那就更好了。但在我继续下去之前,我想问一下是否有关于这个主题的最佳实践解决方案。

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

我最终通过代理方法调用每个人 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()}" />

我最后调用了一个 "generic" 方法,传递了当前的 selection 和实际的列表,最后将这个 selection 添加到返回的列表中,如果不存在的话:

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

因此,每当 selected 值 A 不再是源列表的一部分时,代理方法就会添加它,从而使 select 字段能够显示它再次。对于 "new" 个作品,A 不再是来源列表的一部分,因此用户无法再 select A.