I\'m using a select one menu to do navigation to different parts of my site:
<
There are many ways to ahieve what you want. First of all, I will describe alternatives to your approach and then will post some remarks on SEO.
First of all, you could handle your navigation via a normal form submit, when user implicitly submits a form on a change event:
<h:form>
<h:selectOneMenu value="#{bean.currentPage}" converter="pageConverter" onchange="submit()">
<f:selectItems value="#{bean.pages}" var="page" itemLabel="#{page.name}" />
</h:selectOneMenu>
<h:commandButton value="submit" action="#{bean.handleNavigation}" style="display:none"/>
</h:form>
with
@FacesConverter("pageConverter")
and managed bean (@ManagedBean Bean
) with
private List<Page> pages;
private Page selectedPage;
public String handleNavigation(){
//do some job before navigation
return (selectedPage == null) ? null : selectedPage.getUrl();
}
and model class
class Page {
private String name;//title in links
private String url;//JSF view-id
}
You can use your dropbox to keep the choice of user selection and have a button to perform navigation:
<h:form>
<h:selectOneMenu value="#{bean.currentPage}" converter="pageConverter">
<f:selectItems value="#{bean.pages}" var="page" itemLabel="#{page.name}" />
</h:selectOneMenu>
<h:commandButton value="Navigate" action="#{bean.performNavigation}"}/>
</h:form>
with the same model as above.
<h:link>
sDo you navigation jobs with simple <h:link>
s:
<ul>
<ui:repeat var="page" value="#{bean.pages}>
<li>
<h:link value="#{page.name}" outcome="#{page.url}" />
</li>
</ui:repeat>
</ul>
and style this menu accordingly.
SEO is increasingly important nowadays, so following its rules is essential. It is important to use an url rewriting solution in addition to naming on-page links with the (basic) Page
class as above, so that the user sees www.site.com/contact-us
in his browser and not www.site.com/contact.xhtml
.
The simplest way to follow IMHO is to use Prettyfaces, which is a great solution, to my taste. It allows you to set up your rewritten urls very easily (and rewrite all your internal urls in JSF components).
To enhance your site SEO component you could introduce a field seoUrl
in Page
model class, and then have a Prettyfaces mapping which will show SEO-friendly url (i.e. www.site.com/contact-us
) instead of JSF view-id (i.e. www.site.com/contact.xhtml
) in web browser's address bar.
www.site.com/contact-us.xhtml
, but why would there be 6 excessive characters - www.site.com/contact-us
would be better;/pages/articles/general/how-to-do-jsf.xhtml
, but it would be better to have and url like www.site.com/articles/how-to-do-jsf
with path reflected in page, if necessary;jsf-bp.xhtml
), or unmeaningful ones (article23.xhtml
), but it would be better to show an url of www.site.com/article/jsf-best-practices-for-beginners
;.xhtml
, .jsf
, etc. may lead users (and probably search engines) into thinking that the content is dynamic (meaning that content is rendered from a template), like in www.site.com/product.xhtml?id=12345
, but static content should be preferred, as users (and probably search engines) would think that such an URL describes a compeletely stateless page, like in www.site.com/products/jsf-book-for-advanced-users
. Moreover, it greately enhances site usability, which is also of great importance;?id=12345
) and names for path-parameters (/jsf-book-for-advanced-users
);www.site.com/products/jsf-book-for-advanced-users
: this type of url structure will render a unique product page, and removal of /jsf-book-for-advanced-users
may render a complete catalogue. But what shall happen if you have www.site.com/product.xhtml?name=jsf-book-for-advanced-users
for products and www.site.com/catalogue.xhtml
for catalogue? The logic is unclear for a user, rewriting enables structuring of your URLs;I do not claim that sources referred to by me are undisputable, or are extremely authorative, or their input needs to be applied to every web application, etc. but I do believe that well-structured, user-friendly sites that exist for a long time in production tend to follow those rules.
just create function navigate as :
<p:selectOneMenu value="#{navigator.outcome}">
<f:selectItem itemLabel="Select page..." />
<f:selectItem itemValue="page1" itemLabel="Page 1" />
<f:selectItem itemValue="page2" itemLabel="Page 2" />
<f:selectItem itemValue="page3" itemLabel="Page 3" />
<p:ajax event="change" listener="#{navigator.navigate}" />
</p:selectOneMenu>
public void navigate() {
FacesContext context = FacesContext.getCurrentInstance();
NavigationHandler navigationHandler = context.getApplication()
.getNavigationHandler();
navigationHandler.handleNavigation(context, null, outcome
+ "?faces-redirect=true");
}
Use custom content with <p:column>
with therein a <h:link>
.
Bean:
private List<Page> pages;
@PostConstruct
public void init() {
pages = new ArrayList<Page>();
pages.add(new Page("Page 1", "/page1.xhtml"));
pages.add(new Page("Page 2", "/page2.xhtml"));
pages.add(new Page("Page 3", "/page3.xhtml"));
}
View:
<p:selectOneMenu var="page">
<f:selectItems value="#{bean.pages}" var="page" itemLabel="#{page.title}" />
<p:column>
<h:link value="#{page.title}" outcome="#{page.viewId}" />
</p:column>
</p:selectOneMenu>
Note that this doesn't work with List<SelectItem>
nor individual <f:selectItem>
entries. You really need to provide a List<Entity>
(wherein Entity
is Page
in the above example).
This generates a <table>
with fullworthy and crawlable (and clickable!) <a>
elements.