JSF:带有自定义事件的 <f:event>

Dar*_*rit 5 jsf event-handling jsf-2

我不知道是否可以使用 f:event 使用自定义事件。Ed Burns 的书建议将 @NamedEvent 注释添加到 Event 类并使用:

<f:event type="com.foo.bar.myEvent" listener="#{listener} />
Run Code Online (Sandbox Code Playgroud)

但该事件似乎永远不会被实例化。

从我的角度来看,这是有道理的,因为组件对事件一无所知,例如何时发布,因此这可能仅对自定义组件作者有用。

另一方面,如果从 PostAddToViewEvent 派生,标准组件应该能够发布事件。无论如何,标准组件似乎永远不会发布自定义事件。

我错过了什么吗?是否有一种方便的方法可以将自定义事件与标准组件一起使用?

这是我想做的:

<h:inputText id="input">
    <f:event type="foo.bar.MyCustomEvent" /> 
</h:inputText>
Run Code Online (Sandbox Code Playgroud)
public class MyCustomEvent extends javax.faces.event.PostAddToViewEvent {
}
Run Code Online (Sandbox Code Playgroud)

小智 2

是的,你可以为此你必须重写 jsf render 或组件类中的某些方法

public class MyComponent extends HtmlInputText       or   public class MyRenderer extends TextRenderer

@Override
public void decode(FacesContext context, UIComponent component) {
    super.decode(context, component);

    String sourceName = context.getExternalContext().getRequestParameterMap().get("javax.faces.source");
    if(sourceName != null && sourceName.equals(component.getClientId())){
        component.queueEvent(new MyEvent(component));
    }
}
Run Code Online (Sandbox Code Playgroud)

但在 MyEvent 类中你必须重写一些方法

@Override
public PhaseId getPhaseId() {
    return PhaseId.INVOKE_APPLICATION;
}
Run Code Online (Sandbox Code Playgroud)

它将定义该事件将在哪个面处理(默认情况下它是 ANY_PHASE 并且事件触发器在其注册的同一阶段)

@Override
public boolean isAppropriateListener(FacesListener listener) {
    return false;
}
Run Code Online (Sandbox Code Playgroud)

如果你有适当的监听器,它必须返回 true 如果你有适当的 MyEvent 监听器,那么 JSF 将在触发事件时调用该监听器的 processAction(ActionEvent event) 方法,否则它将调用组件类中的广播方法,该方法必须由开发人员覆盖

@Override
public void broadcast(FacesEvent event) throws AbortProcessingException {
    super.broadcast(event);

    if(event instanceof MyEvent){
        try {
            processMyEvent(event);
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

即使您可以使用组件queueEvent(FacesEvent event)方法自己注册任何事件,如果getPhaseId()方法未被覆盖,它也会注册事件并通过MyEvent类中的getPhaseId()方法获取将触发的阶段devloper 那么它将在其注册的同一阶段触发

  • 这个答案具有误导性且不完整。作者似乎将 `FacesEvent` 与 `ComponentSystemEvent` 混淆并将它们混合在一起。这个答案至少对于按照OP的要求创建和发布自定义“ComponentSystemEvent”没有任何帮助。 (2认同)