Validation JSF2——保存所有有效的组件值
我需要创建一个javascript函数,当调用该函数时,它会将所有有效组件保存在JSF2.0表单上。因为完整的表单永远不会作为一个整体有效,所以我需要找出一种方法来运行每个组件的生命周期,这样,如果验证阶段成功,模型将被更新并最终保存 理想情况下,这需要是一个单独的ajax请求,因为使用单独的ajax请求迭代每个组件会非常低效 以前有人解决过这个问题吗?如果没有,你能给我一些关于可能实现的建议吗 编辑: 以下是我所拥有的到目前为止似乎运行良好的产品:Validation JSF2——保存所有有效的组件值,validation,jsf,jsf-2,components,partial,Validation,Jsf,Jsf 2,Components,Partial,我需要创建一个javascript函数,当调用该函数时,它会将所有有效组件保存在JSF2.0表单上。因为完整的表单永远不会作为一个整体有效,所以我需要找出一种方法来运行每个组件的生命周期,这样,如果验证阶段成功,模型将被更新并最终保存 理想情况下,这需要是一个单独的ajax请求,因为使用单独的ajax请求迭代每个组件会非常低效 以前有人解决过这个问题吗?如果没有,你能给我一些关于可能实现的建议吗 编辑: 以下是我所拥有的到目前为止似乎运行良好的产品: @ManagedBean(name = "p
@ManagedBean(name = "partialAppSaveBean")
@RequestScoped
public class PartialAppSaveBean implements Serializable {
protected static final Logger LOGGER = LoggerFactory.getLogger(PartialAppSaveBean.class);
private static final long serialVersionUID = 1L;
/**
* Save any valid Application values
*
* @param event
*/
public void saveData(AjaxBehaviorEvent event) {
final FacesContext context = FacesContext.getCurrentInstance();
UIForm form = getParentForm(event.getComponent());
Set<VisitHint> hints = EnumSet.of(VisitHint.SKIP_UNRENDERED);
form.visitTree(VisitContext.createVisitContext(context, null, hints), new VisitCallback() {
@Override
public VisitResult visit(VisitContext context, UIComponent component) {
if (component instanceof UIInput) {
UIInput input = (UIInput) component;
input.validate(context.getFacesContext());
if (input.isValid() && input.getValue() != null) {
ValueExpression valueExpression = input.getValueExpression("value");
if (valueExpression != null
&& valueExpression.getExpressionString() != null) {
try {
valueExpression.setValue(context.getFacesContext().getELContext(), input.getValue());
} catch (Exception ex) {
LOGGER.error("Expression [ " + valueExpression.getExpressionString() +
"] value could not be set with value [" + input.getValue() + "]", ex);
}
}
}
}
return VisitResult.ACCEPT;
}
});
//Save data here
}
/**
* Returns the parent form for this UIComponent
*
* @param component
* @return form
*/
private static UIForm getParentForm(UIComponent component) {
while (component.getParent() != null) {
if (component.getParent() instanceof UIForm) {
return (UIForm) component.getParent();
} else {
return getParentForm(component.getParent());
}
}
return null;
}
}
@ManagedBean(name=“partialAppSaveBean”)
@请求范围
公共类PartialAppSaveBean实现可序列化{
受保护的静态最终记录器Logger=LoggerFactory.getLogger(PartialAppSaveBean.class);
私有静态最终长serialVersionUID=1L;
/**
*保存所有有效的应用程序值
*
*@param事件
*/
公共作废保存数据(AjaxBehaviorEvent事件){
final FacesContext context=FacesContext.getCurrentInstance();
UIForm form=getParentForm(event.getComponent());
设置提示=EnumSet.of(visitint.SKIP\u未指定);
form.visitTree(VisitContext.createVisitContext(context,null,hints),new VisitCallback(){
@凌驾
公共访问结果访问(VisitContext上下文,UIComponent组件){
if(UIInput的组件实例){
UIInput=(UIInput)组件;
验证(context.getFacesContext());
if(input.isValid()&&input.getValue()!=null){
ValueExpression=input.getValueExpression(“值”);
if(valueExpression!=null
&&valueExpression.getExpressionString()!=null){
试一试{
valueExpression.setValue(context.getFacesContext().getELContext(),input.getValue());
}捕获(例外情况除外){
LOGGER.error(“表达式[”+valueExpression.getExpressionString()+
无法使用值[“+input.getValue()+”],ex)设置“]值;
}
}
}
}
返回VisitResult.ACCEPT;
}
});
//在此处保存数据
}
/**
*返回此UIComponent的父窗体
*
*@param组件
*@报税表
*/
专用静态UIForm getParentForm(UIComponent组件){
while(component.getParent()!=null){
if(component.getParent()instanceof UIForm){
返回(UIForm)组件。getParent();
}否则{
返回getParentForm(component.getParent());
}
}
返回null;
}
}
调用类似于:
<h:commandButton
id="saveData">
<f:ajax listener="#{partialAppSaveBean.saveData}" execute="@form" immediate="true" onevent="onPartialSave" />
</h:commandButton>
您可以在上使用
FacesContext context=FacesContext.getCurrentInstance();
UIForm form=getForm();
Map validValues=new HashMap();
设置提示=EnumSet.of(visitint.SKIP\u未指定);
form.visitTree(VisitContext.createVisitContext(context,null,hints),new VisitCallback(){
@凌驾
公共访问结果访问(VisitContext上下文,UIComponent组件){
if(UIInput的组件实例){
UIInput=(UIInput)组件;
if(input.isValid()){
validValues.put(input.getClientId(context.getFacesContext()),input.getValue());
}
}
返回VisitResult.ACCEPT;
}
});
不错。如果input.isValid(),是否有一种简单的方法来转换值并更新组件绑定到的模型?这取决于功能需求。表单是否已提前提交/作废,而您仅执行了
?或者您希望提交并处理整个表单并接管JSF验证吗?如果是后者,则在If(input.isValid())
之前调用input.validate(context.getFacesContext())
。顺便说一下,这也将执行转换。它不会更新模型值,因此您必须通过input.getValue()
获取它。要求是,当用户试图退出时,我将使用onbeforeunload方法提示他们是否要保存数据(即使数据不完整),因此我将调用等效的。然后我需要更新有效UIInput元素的模型并保存模型层次结构。顺便说一句,这是一个关于OmniFaces的有趣想法。这将是对一个已经非常优秀的项目的最优秀的补充。我认为你提供的蓝图应该能满足我今天的需要。是时候去写些代码了。
FacesContext context = FacesContext.getCurrentInstance();
UIForm form = getFormSomehow();
Map<String, Object> validValues = new HashMap<String, Object>();
Set<VisitHint> hints = EnumSet.of(VisitHint.SKIP_UNRENDERED);
form.visitTree(VisitContext.createVisitContext(context, null, hints), new VisitCallback() {
@Override
public VisitResult visit(VisitContext context, UIComponent component) {
if (component instanceof UIInput) {
UIInput input = (UIInput) component;
if (input.isValid()) {
validValues.put(input.getClientId(context.getFacesContext()), input.getValue());
}
}
return VisitResult.ACCEPT;
}
});