Как перенаправить на якорь в JSF? - PullRequest
8 голосов
/ 06 июля 2011

Допустим, у меня есть это действие в управляемом компоненте JSF:

public String doSomething() {
    FacesContext.getCurrentInstance().getExternalContext().getFlash().put("msg", "Something was done successfully");
    return "view?faces-redirect=true";
}

Мой view имеет элемент привязки с идентификатором msg.Я хочу, чтобы URL имел этот якорь (для вопросов доступности), например:

view.jsf#msg

Или каков мой шаблон фильтра FacesServlet.

return "view#msg?faces-redirect=true";, очевидно, не будет работать, потому что JSF (mojarraпо крайней мере) попробует оценить view#msg как представление.

Поэтому мой вопрос заключается в том, как заставить JSF перенаправить на URL с #msg в конце.

Ответы [ 2 ]

10 голосов
/ 06 июля 2011

, потому что JSF (по крайней мере, мохарра) попытается оценить view#msg как представление

О, это противно.Это определенно стоит просьба об улучшении у мальчиков JSF / Mojarra.

Лучше всего отправлять перенаправление вручную с помощью ExternalContext#redirect().

public void doSomething() throws IOException {
    ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
    ec.getFlash().put("msg", "Something was done successfully");
    ec.redirect("view.xhtml#msg");
}

(при условии, что FacesServlet сопоставлен с *.xhtml)

Кроме того, вы можете условно визуализировать фрагмент JS, который делает это вместо этого.

<ui:fragment rendered="#{not empty flash.msg}">
    <script>window.location.hash = 'msg';</script>
</ui:fragment>
0 голосов
/ 30 июня 2017

Вы пытаетесь создать недопустимый URL - фрагмент (#) всегда является последней частью URL.

return "view?faces-redirect=true#msg" будет правильным URL.

К сожалению, этот фрагмент по умолчанию удаляется NavigationHandler, по крайней мере, в JSF 2.2.

Хотя оба варианта BalusC также работают, у меня есть третий вариант. Оберните NavigationHandler и ViewHandler небольшим патчем:

public class MyViewHandler extends ViewHandlerWrapper {

    public static final String REDIRECT_FRAGMENT_ATTRIBUTE = MyViewHandler.class.getSimpleName() + ".redirect.fragment";

    // ... Constructor and getter snipped ...

    public String getRedirectURL(final FacesContext context, final String viewId, final Map<String, List<String>> parameters, final boolean includeViewParams) {
        final String redirectURL = super.getRedirectURL(context, viewId, removeNulls(parameters), includeViewParams);
        final Object fragment = context.getAttributes().get(REDIRECT_FRAGMENT_ATTRIBUTE);
        return fragment == null ? redirectURL : redirectURL + fragment;
    }

}

public class MyNavigationHandler extends ConfigurableNavigationHandlerWrapper {

    // ... Constructor and getter snipped ...

    public void handleNavigation(final FacesContext context, final String fromAction, final String outcome) {
        super.handleNavigation(context, fromAction, 
            storeFragment(context, outcome));
    }

    public void handleNavigation(final FacesContext context, final String fromAction, final String outcome, final String toFlowDocumentId) {
        super.handleNavigation(context, fromAction, 
            storeFragment(context, outcome), toFlowDocumentId);
    }

    private static String storeFragment(final FacesContext context, final String outcome) {
        if (outcome != null) {
            final int hash = outcome.lastIndexOf('#');
            if (hash >= 0 && hash + 1 < outcome.length() && outcome.charAt(hash + 1) != '{') {
                context.getAttributes().put(MyViewHandler.REDIRECT_FRAGMENT_ATTRIBUTE, outcome.substring(hash));
                return outcome.substring(0, hash);
            }
        }
        return outcome;
    }
}

(В любом случае мне пришлось создать оболочку для ViewHandler из-за исправления для JAVASERVERFACES-3154)

...