我似乎无法使视图作用域托管bean与setPropertyActionListener一起使用:
<h:commandButton value="Edit" action="edit-company.xhtml">
<f:setPropertyActionListener target="#{companyHolder.item}" value="#{company}"/>
</h:commandButton>
如果companyHolder是会话或请求作用域,但如果其视图作用域,则无效。这是正常的吗?
答案 0 :(得分:6)
创建新视图时,会创建一个全新的视图范围bean。目标视图包含视图范围bean的不同实例,而不是使用表单的初始视图上的操作方法设置属性的位置。
乍一看确实不直观,但这就是视图范围的工作原理。只要视图存在,视图范围的bean就会存在。毕竟这很有意义。
您最好的选择是使用<f:param>
代替<f:setPropertyActionListener>
,并让目标视图按<f:viewParam>
设置。
E.g。
<h:commandButton value="Edit" action="edit-company.xhtml">
<f:param name="companyId" value="#{company.id}"/>
</h:commandButton>
与
<f:metadata>
<f:viewParam name="companyId" value="#{bean.company}" required="true" />
</f:metadata>
和
@ManagedBean
@ViewScoped
public class Bean {
private Company company;
// ...
}
和
@FacesConverter(forClass=Company.class)
public class CompanyConverter implements Converter {
@Override
public void getAsObject(FacesContext context, UIComponent component, Object value) throws ConverterException {
try {
return companyService.find(Long.valueOf(value));
} catch (Exception e) {
throw new ConverterException(new FacesMessage(
String.format("Cannot convert %s to Company", value)), e);
}
}
// ...
}
作为完全不同的替代方案,您还可以返回void
或null
并有条件地渲染包含,然后导航回同一视图。
<ui:include src="#{bean.editmode ? 'edit' : 'view'}.xhtml" />
但是,如果您需要支持GET而不是POST(根据<h:commandButton>
,您需要替换<h:button>
),这不起作用。