如果我想将焦点设置到无法验证的字段。我可以使用<p:focus context='@form'/>
来实现这个简单的案例,很简单。但我的问题是,并非所有验证都可以在前端执行。例如,我希望用户输入用户名,当用户提交表单时,bean将检查数据库是否已存在用户名,如果存在,则将错误消息设置为该字段并将焦点设置为该字段。在这种情况下,<p:focus />
标签不再起作用,因为它实际上已经通过了前端验证。
我发现this回答并尝试实现它,我会说它只能部分工作。为什么?因为如果通过为它声明变量来手动设置bean的焦点,它将覆盖<p:focus context='@form'/>
标记。当此焦点标记失去其功能时,如果有任何前端验证失败,它将不再将焦点带到该特定字段。
我尝试过使用widgetVar
来执行焦点。我为我的字段声明了一个widgetVar
名称,比如widgetVar='username'
,在托管bean中,我使用以下代码来关注它:
RequestContext.getCurrentInstance().execute("PF('username').focus()");
不幸的是,它不起作用。不确定execute()
是否以这种方式工作或声明有问题。对不起我的英语不好,任何帮助或建议将不胜感激。
正如评论中所提到的,PrimeFaces
class中提供了一种实用方法:
PrimeFaces.current().focus(String expression)
表达式相对于view root,或者:
PrimeFaces.current().focus(String expression, UIComponent base)
表达式相对于提供的基本组件。
只需检查一下PrimeFaces在focus
renderer中的作用:
ResponseWriter writer = context.getResponseWriter(); UIComponent forComponent = SearchExpressionFacade.resolveComponent( context, focus, focus.getFor()); String clientId = forComponent.getClientId(context); writer.write("$(function(){"); writer.write("PrimeFaces.focus('" + clientId + "');"); writer.write("});");
你可以在一个动作中做同样的事情:
public void focus(String expression) {
FacesContext context = FacesContext.getCurrentInstance();
UIComponent forComponent = SearchExpressionFacade.resolveComponent(
context,
UIComponent.getCurrentComponent(context),
expression
);
String clientId = forComponent.getClientId();
RequestContext.getCurrentInstance().execute("PrimeFaces.focus('" + clientId + "');");
}
请注意,我正在使用触发操作的命令按钮作为搜索表达式的源,并且您在此处不需要$(function(){...}
。
您唯一需要做的是,不要将clientId
作为action方法的参数,而是创建代码来确定应该获得焦点的组件。
使用XHTML测试:
<h:form id="main">
<p:inputText id="text1"/>
<p:inputText id="text2"/>
<p:commandButton value="Focus 1" action="#{myBean.focus('text1')}"/>
<p:commandButton value="Focus 2" action="#{myBean.focus('text2')}"/>
<p:commandButton value="Form" action="#{myBean.focus('@form')}"/>
</h:form>