1

ページの preRender コードで、faces メッセージを追加してから、次のように別のページに移動します。

if(error){
addMessageToComponent(null,"AN ERROR HAS OCCURRED");
FacesContext.getCurrentInstance().getExternalContext().getFlash()
                .setKeepMessages(true);
navigateActionListener("myoutcome");
}

メッセージとナビゲーションを追加するための util メソッドは次のとおりです。

public static String getClientId(String componentId)
    {
        FacesContext context = FacesContext.getCurrentInstance();
        UIViewRoot root = context.getViewRoot();

        UIComponent c = findComponent(root, componentId);
        return c.getClientId(context);
    }

    public static UIComponent findComponent(UIComponent c, String id)
    {
        if (id.equals(c.getId())) { return c; }
        Iterator<UIComponent> kids = c.getFacetsAndChildren();
        while (kids.hasNext())
        {
            UIComponent found = findComponent(kids.next(), id);
            if (found != null) { return found; }
        }
        return null;
    }

    /**
     * @param componentId
     *            : the id for the jsf/primefaces component without formId:
     *            prefix. <br>
     *            if you use null then the message will be added to the
     *            h:messages component.
     **/
    public static void addMessageToComponent(String componentId, String message)
    {

        if (componentId != null)
            componentId = GeneralUtils.getClientId(componentId);
        FacesContext.getCurrentInstance().addMessage(componentId,
                new FacesMessage(message));
    }

public static void navigateActionListener(String outcome)
    {
        FacesContext context = FacesContext.getCurrentInstance();
        NavigationHandler navigator = context.getApplication()
                .getNavigationHandler();
        navigator.handleNavigation(context, null, outcome);
    }

ただし、メッセージは保存されないため、リダイレクト後に表示されません。

それを修正する方法を教えてください。

4

1 に答える 1

4

イベントはフェーズのpreRenderView最初に実行されます。スコープにメッセージを保持するRENDER_RESPONSEように指示するには遅すぎます。遅くともフェーズFlash中にこれを行うことができます。INVOKE_APPLICATION

これには標準の JSF コンポーネント システム イベントがないため、自作する必要があります。

@NamedEvent(shortName="postInvokeAction")
public class PostInvokeActionEvent extends ComponentSystemEvent {

    public PostInvokeActionEvent(UIComponent component) {
        super(component);
    }

}

これを公開するには、次のものが必要ですPhaseListener:

public class PostInvokeActionListener implements PhaseListener {

    @Override
    public PhaseId getPhaseId() {
        return PhaseId.INVOKE_APPLICATION;
    }

    @Override
    public void beforePhase(PhaseEvent event) {
        // NOOP.
    }

    @Override
    public void afterPhase(PhaseEvent event) {
        FacesContext context = FacesContext.getCurrentInstance();
        context.getApplication().publishEvent(context, PostInvokeActionEvent.class, context.getViewRoot());
    }

}

に次のように登録した後faces-config.xml

<lifecycle>
    <phase-listener>com.example.PostInvokeActionListener</phase-listener>
</lifecycle>

新しいイベントは次のように使用できます。

<f:event type="postInvokeAction" listener="#{bean.init}" />

少なくとも<f:viewParam>.

JSF ユーティリティ ライブラリOmniFacesは、このイベントとイベントをすぐにサポートpreInvokeActionしています。リダイレクト用のfacesmessageの設定も示しているショーケースページも参照してください。

于 2012-10-30T17:50:31.480 に答える