使用绑定和View范围时,如何使JSF验证程序,valueChangeListener和actionListener一次调用,但不能多次调用 [英] How to make JSF validator, valueChangeListener and actionListener be called once but not multiple times when binding and View scope are used

查看:146
本文介绍了使用绑定和View范围时,如何使JSF验证程序,valueChangeListener和actionListener一次调用,但不能多次调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

JSF组件使用binding,支持bean是View scope.组件已设置validatorvalueChangeListener.并且当组件的值改变时,部分请求被发送到服务器.并且validatorvalueChangListener被多次调用,但在请求中不会被调用一次.

The JSF component uses binding and backing bean is of View scope. The component have validator and valueChangeListener set. And when component's value is changed partial request is sent to server. And validator and valueChangListener are called many times but not once within request.

如何使它们在请求期间被调用一次?

How to make them to be called once during request?

如果删除binding,则方法将被正确调用一次.

If remove binding the methods are called correctly once.

但是有可能不删除绑定并使监听器被调用一次吗?

But is it possible to do not remove binding and make listeners be called once?

下一个使用的代码示例:

Sample of used code is next:

<h:inputText id="txt"
             validator="#{myBean.validateValue}"
             valueChangeListener="#{myBean.valueChanged}"
             binding="#{myBean.txtInput}">
   <f:ajax event="valueChange"
           execute="@this"
           render="@this"/>
</h:inputText>

@ViewScoped
@ManagedBean
public class MyBean {

private HtmlInputText txtInput;

public void valueChanged(ValueChangeEvent ve) {
    ...
}

public void validateValue(FacesContext context, UIComponent component, Object value) {
    ...
}

public HtmlTextInput getTxtInput() {
    return txtInput;
}

public void setTxtInput(HtmlTextInput txtInput) {
    this.txtInput = txtInput;
}    

}

如果actionListenercommandLink组件使用绑定并且支持bean具有View scope,则会发生相同的问题.

The same issue takes place for actionListener and commandLink component if it uses binding and backing bean has View scope.

推荐答案

可能的解决方案可能只是覆盖UIInputUICommand用于存储validatorslisteners的类.类别为javax.faces.component.AttachedObjectListHolder.

The possible solution could be just to override class which is used by UIInput and UICommand to store validators and listeners. The class is javax.faces.component.AttachedObjectListHolder.

此类直接将新的listener添加到后备列表中,而不检查是否已经存在相同的listener. 因此,解决方案是检查listener是否存在,然后不添加它.

This class straightforward add new listener to backing list not checking if the same listener already is there. Thus the solution is to check if listener exists and not to add it then.

因此,从jsf-api-2.1.<x>-sources.jar中提取javax.faces.component.AttachedObjectListHolder并将其添加到您的项目中,并放入相应的包中.用这样的方法替换方法add:

So take javax.faces.component.AttachedObjectListHolder from jsf-api-2.1.<x>-sources.jar and add it to your project to the corresponding package. Replace method add with such one:

void add(T attachedObject) {
    boolean addAttachedObject = true;

    if (attachedObject instanceof MethodExpressionActionListener
        || attachedObject instanceof MethodExpressionValueChangeListener
        || attachedObject instanceof MethodExpressionValidator) {

        if (attachedObjects.size() > 0) {
            StateHolder listener = (StateHolder) attachedObject;
            FacesContext context = FacesContext.getCurrentInstance();
            Object[] state = (Object[]) listener.saveState(context);
            Class<? extends StateHolder> listenerClass = listener.getClass();

            for (Object tempAttachedObject : attachedObjects) {
                if (listenerClass.isAssignableFrom(tempAttachedObject.getClass())) {
                    Object[] tempState = (Object[]) ((StateHolder) tempAttachedObject).saveState(context);
                    if (((MethodExpression) state[0]).getExpressionString().equals(((MethodExpression)tempState[0]).getExpressionString())) {
                        addAttachedObject = false;
                        break;
                    }
                }
            }
        }
    }

    clearInitialState();
    if (addAttachedObject) {
        attachedObjects.add(attachedObject);
    }
}

在此验证器之后,即使使用组件绑定和视图",会话"或应用程序"范围,valueChangeListener和actionListener也将仅触发一次.

After that validators, valueChangeListeners and actionListeners will be triggered only once even when component binding and "View", "Session" or "Application" scopes are used.

这篇关于使用绑定和View范围时,如何使JSF验证程序,valueChangeListener和actionListener一次调用,但不能多次调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆