我有这个简单的facelets页面:
<!DOCTYPE html>
<html xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Index</title>
</h:head>
<h:body>
<h:form>
<h:inputText id="firstname" value="#{fooBar.firstname}">
<f:ajax event="keyup" render="echo" execute="myCommandButton"/>
</h:inputText>
<h:commandButton value="Submit" action="#{fooBar.fooBarAction()}" id="myCommandButton"/>
</h:form>
<br/>
<h:outputText id="echo" value="#{fooBar.firstname}"/>
</h:body>
</html>
和Foobar bean如下:
@ManagedBean
@ApplicationScoped
public class FooBar {
private String firstname;
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getFirstname() {
return firstname;
}
public void fooBarAction() {
System.out.println("Foo bar action being executed!!!");
}
}
所以我希望每当我在 inputText 字段中输入内容时,都会看到文本 Foo bar操作正在执行,但事实并非如此。我错过了什么?
编辑:为什么我期待这种行为? 我正在研究这本书Core JavaServer Faces,并在书中注意到:
JSF 2.0将JSF生命周期分为两部分:执行和呈现。
执行包括:恢复视图 - &gt;应用请求值 - &gt;处理 验证 - &gt;更新模型值 - &gt;调用应用程序
当JSF在服务器上执行组件时,它:
- 转换并验证组件的值(如果组件是输入)。
- 将有效输入值推送到模型(如果组件连接到bean属性)。
- 执行操作和操作侦听器(如果组件是操作)。
所以在这里,myCommandButton应该被执行,不是吗?并且组件的执行意味着要执行的操作?
编辑#2
此引用来自 JavaServer Faces完整参考
如果未指定侦听器,则将调用唯一的操作 在Invoke Application阶段期间将是对应的阶段 到execute属性中列出的ActionSource组件。
据我所知,在我的例子中,我有一个实现ActionSource接口(myCommandButton)的组件,并且应该执行该组件的action属性。但事实并非如此?
答案 0 :(得分:5)
execute
的{{1}}属性基本上告诉JSF在回发期间通过JSF生命周期处理哪些组件。即它基本上告诉JSF它必须执行哪些组件应用请求值,进程验证,更新模型值和调用应用程序阶段。应用请求值阶段将收集(解码)提交的HTML表单(输入和按钮)值。验证阶段将对提交的值运行转换/验证。更新模型值阶段将在backing bean中设置提交/转换/验证的值。调用应用程序阶段将执行提交的操作。请注意,关键是JSF将根据提交的 HTML表单值执行此操作。
换句话说,<f:ajax>
属性完全是服务器端。正如您所期待的那样,它不是客户端。您似乎希望它告诉webbrowser提交指定的组件,就像您单击它一样。这不是真的。按钮值仅在实际被按下/单击/提交时通过JSF生命周期处理。
如果在execute
属性中指定了按钮,并且JSF在处理生命周期期间确定按钮值实际上未提交(即在HTTP请求参数映射中完全没有),则JSF将不排队在申请请求值阶段期间的行动事件。因此,在调用应用程序阶段期间不会调用任何内容。
当触发execute
事件时,它实际上是作为动作源的封闭组件。因此,您应该在其上挂钩所需的动作侦听器。您可以使用<f:ajax>
listener
属性。
<f:ajax>
<h:form>
<h:inputText id="firstname" value="#{fooBar.firstname}">
<f:ajax event="keyup" listener="#{fooBar.keyupListener}" render="echo" />
</h:inputText>
<h:commandButton value="Submit" action="#{fooBar.fooBarAction}" id="myCommandButton"/>
</h:form>
答案 1 :(得分:1)
必须在f:ajax
方面定义要在每个键击上调用的动作和/或actionListener。您已在下面的h:commandButton
中定义了您的操作。 JSF没有看到ajax facet和按钮之间的任何连接。除技术原因外,至少有两个原因使这种行为变得合理:
f:ajax
方面。例如,您可以为事件定义不同的方面&#34; keyup&#34;和&#34;模糊&#34;。如果定义了多个方面,则可能希望它们调用不同的后端bean方法。您不希望它们调用表单的任何其他命令按钮。请记住,它可能是&#34;取消&#34;按钮,如果在每次击键时触发它会有点不方便。所以你从Core JSF书中引用的陈述是正确的。每个action和actionListener都会被执行。你的错误在于你在心理上将范围扩展到整个表格。相反,JSF只关注围绕AJAX方面的组件。
JavaServer Faces Complete Reference的引用对我来说听起来不对。当既没有指定动作也没有指定actionListener时,&#34;调用应用程序&#34; JSF阶段没有做任何事情。输入被发送到服务器,它被验证,它存储在后端bean中,它用于再次呈现页面。但是没有调用任何动作,因为你没有指定要调用的动作。