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
.
在我们的应用程序中,我们有各种 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
.