我目前正在使用 Primefaces 4.0 和 JEE 6 开发一个项目。我们使用 maven 作为构建工具,并且我们有一个 JBoss 应用程序服务器。
所以这应该很简单。当发生验证错误时,我应该阻止 View 中的制表符更改。没什么大不了的,但是必须要做。
接下来发生的事情让我大吃一惊,但首先我做了什么:
- 定义一个支持 Bean 来处理事件。
- 在那里定义一个监听器。
- 使用
<p:ajax />
向我的 bean 触发 tabChange 事件。
嗯,在那之前一切都很简单。当没有验证错误时,它工作得很好。然后我尝试根据我的 Model-Bean 验证 View 中的值,但很快就停止了。
一旦我自愿在 View 中产生错误,以触发面孔消息,tabChange 监听器就不再执行。事实上,甚至连 @RequestScoped
都没有。构造了具有监听器的 Controller 类。
我在 Weld CDI maven 原型(prototype)的帮助下创建了一个最小的工作示例。
现在我站在这里,束手无策,向您展示我的例子:
home.xhtml:
我删除了周围的 xml 声明和 ui:define 内容,但这就是我重现它的方法。
<h1>Hello World!</h1>
<p>
Your CDI bean
<code>HelloWorld</code>
says <span style="color: blue;">#{helloWorld.text}</span> using the
Unified EL.
</p>
<h:form id="bv">
<h2>Bean Validation examples</h2>
<p>Enforces annotation-based constraints defined on the model
class.</p>
<p:tabView id="tabView" effect="fade"
effectDuration="normal">
<p:ajax event="tabChange" update="tabView" listener="#{controller.tabChange}"/>
<p:tab title="Tab 1">
<table>
<tr>
<th style="text-align: right;"><h:outputLabel for="letters"
value="Letters:" /></th>
<td><p:inputText id="letters" value="#{helloWorld.letters}" />
<p:message for="letters" errorClass="invalid" /></td>
</tr>
</table>
</p:tab>
<p:tab title="Tab 2">
<p>Random text to be displayed</p>
</p:tab>
</p:tabView>
</h:form>
Controller.java:
这里我只删除了包声明,以保护无辜者。
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
import org.primefaces.event.TabChangeEvent;
@Named
@RequestScoped
public class Controller implements Serializable {
private static final long serialVersionUID = -1126987875831465303L;
public Controller() {
}
@PostConstruct
public void init() {
System.out.println("Constructed " + this.getClass().getSimpleName());
}
public void tabChange(final TabChangeEvent event) {
System.out.println("Listener was reached");
}
}
最后但并非最不重要的一点是,模型 bean,比原型(prototype)提供的稍稍缩短了:
HelloWorld.java:
我再次删除了命名空间声明。
import javax.annotation.PostConstruct;
import javax.enterprise.inject.Model;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.NotEmpty;
public @Model
class HelloWorld {
private final String text = "Hello World!";
private String letters;
public HelloWorld() {
}
@PostConstruct
public void initialize() {
System.out
.println(this.getClass().getSimpleName() + " was constructed");
}
public String getText() {
return text;
}
@NotNull
@NotEmpty
@Pattern(regexp = "[A-Za-z]*", message = "must contain only letters")
public String getLetters() {
return letters;
}
public void setLetters(final String letters) {
this.letters = letters;
}
}
最佳答案
看来 JSF 生命周期干扰了我想做的事情。
看来,事件监听器只会在“调用应用程序”阶段被调用。
假设,很明显,在“流程验证”之后,我们跳到“渲染响应”,并且整个支持 bean 被忽略。
可以使用immediate="true"
来规避这个问题。 ,但在意识到有一种更好的解决方案可以解决我使用的根本问题时,即 <p:wizard />
相反,这正是我想要的。
关于validation - TabChangeEvent 未到达监听器并出现验证错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25302154/