How to redirect to anchor in JSF?

Let's say I have this action in a managed JSF Bean:

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

My view has a binding element with id msg . I want url to have this anchor (for accessibility), for example:

 view.jsf#msg 

Or whatever my FacesServlet filter template is.

return "view#msg?faces-redirect=true"; obviously will not work because JSF (at least mojarra) will try to evaluate view#msg as a view.

So my question is how to make JSF redirect to URL with #msg at the end.

+7
source share
2 answers

since JSF (at least mojarra) will try to evaluate view#msg as a view

Oh, that’s disgusting. It is definitely worth asking for improvements in JSF / Mojarra boys.

It is best to send the redirect manually using 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"); } 

(assuming FacesServlet maps to *.xhtml )

Alternatively, you can conditionally display the part of JS that does this instead.

 <ui:fragment rendered="#{not empty flash.msg}"> <script>window.location.hash = 'msg';</script> </ui:fragment> 
+10
source

You are trying to create an illegal URL - the snippet ( # ) is always the last part of the URL.

return "view?faces-redirect=true#msg" will be the correct URL.

Unfortunately, this snippet is shared by default by the NavigationHandler , at least in JSF 2.2.

While two options of BalusC are working , I have a third option. Wrap the NavigationHandler and ViewHandler small patch:

 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; } } 

(I still had to create a wrapper for ViewHandler due to a fix for JAVASERVERFACES-3154)

0
source

All Articles