In my application after clicking to a link I want to focus to a part of a page after the page load. With static html we can do this by code parts below.
Go to Chapter 4
and the chapter 4 is defined;
<h2><a name="C4">Chapter 4</a></h2>
<p>This chapter explains ba bla bla</p>
In jsf 2 I can not find even name attribute in order to use for this purpose.
Any help will greatly be appreciated.
In JSF, the name attribute is computed based on the combination of the 'id' atribute of the jsf component and the 'id' attribute of the form. The reason for this is explained by BalusC here. So if you specify an id for a JSF component, then the name is also computed for it.
Anyways, starting HTML5 usage of name attribute for <a> tag is made obsolete instead it is recommended to use the id attribute of the nearest container. So do not rely on the name attribute.
Though you can try to focus any of these:
<h2 id="top4">This is a heading</h2> or
<h2><a id="top4">This is a heading</a></h2>
Or simply focus a container on the target page like this:
In HTML 4.01
<div id="top4">
<h2>This is a heading</h2>
<p>This is a paragraph</p>
</div>
In HTML 5
<article id="top4">
<h2>This is a heading</h2>
<p>This is a paragraph</p>
</article>
Now in JSF, this is how you focus the container on the target page:
When the outcome is a different page but in the same application:
<h:link id="link1" value="link1" outcome="welcome" fragment="top4" />
where the outcome is welcome.xhtml which is relative to the context root, and "top4" is the id of the container to be focused when the target page is rendered.
When linking an external site:
<h:outputLink id="link2" value="http://www.msn.com/#spotlight">link2</h:outputLink>
Within the same page:
<h:link id="link3" value="link3" fragment="top4" />
Here there is no outcome specified, so the outcome will be the same page.
See also:
http://dev.w3.org/html5/markup/a.html
h:link
h:outputLink
Related
I'm using JSF and Materialize to develop an e-commerce site. I had no problem so far: the form to insert new products in the db works fine, login and registration forms too. Now I'm trying to create a product's catalog, so I need to visualize on the page all the products, but the code isn't interpreted correctly. In inspect element, inside <div class="card-image"> there's no code.
Here's my products.jsp page:
<div class="row">
<div class="col s12 z-depth-3">
<div class="card">
<div class="card-image">
<f:view>
<h1>Products</h1>
<h:form>
<table>
<tr>
<th>Name</th>
<th>Price</th>
</tr>
<c:forEach var="product" items="#{productController.products}">
<tr>
<td><h:commandLink
action="#{productController.findProduct}"
value="#{product.name}">
<f:param name="id" value="#{product.id}" />
</h:commandLink></td>
<td>${product.price}</td>
</tr>
</c:forEach>
</table>
</h:form>
</f:view>
</div>
</div>
</div>
</div>
That's the page on the browser:
Instead if I use only the JSF code it works fine. Do you know how to fix that problem? Thank you all.
Don't use HTML DOM inspector in webbrowser to explore the JSF-generated HTML output. The HTML DOM inspector only shows browser's interpretation of the raw HTML output. In case browser doesn't recognize a certain element as per the doctype, or misses an element while it's expected as per the doctype, or finds an element in the wrong place as per the doctype, then the average webbrowser will leniently hide, autoinsert or move it (otherwise surely half of Internet would be broken).
Always look at raw HTML output by rightclick and View page source (or press Ctrl+U in Chrome) in case you want to explore the real JSF-generated HTML output.
My bet that you still see unparsed JSF/JSTL tags in there. This question is then already answered in JSF returns blank/unparsed page with plain/raw XHTML/XML/EL source instead of rendered HTML output. That HTTP 500 error in your browser console confirms this more. You're opening the page using .jsp extension instead of whatever is being mapped on FacesServlet which is apparently /faces/*. Note that while the answer deals with JSP's successor Facelets (JSP is deprecated in JSF more than 5 years ago), the same principle applies to JSP as well. You need to ensure that the FacesServlet is invoked in order to get JSF tags to run. In case you actually got a HTTP 500 error on that, then you should read (or search) the exception and stack trace for the answer.
TL;DR
Is there something like composite's cc.clientId that will give me the id of a custom tag?
Details:
I'd like a custom tag that will render a label, a value, and an icon. When the icon is clicked, a Bootstrap modal is supposed to open up that will edit the value.
<ui:composition>
<div> #{field.label}: #{field.value}
<a class="icon-pencil" data-target="#editForm" data-toggle="modal">
</div>
<h:form id="editForm" class="modal hide fade" role="dialog" ...>
... there's an input here linked to field.value ...
</h:form>
</ui:composition>
I can use the tag with <my:editor />. When I do so within a ui:repeat, an id is prepended to the editForm so that it renders with id j_idt104:editForm. So I need to modify the data-target to include the id.
This would be really easy with a composite component because I have access to the id via cc.clientId:
data-target="\##{cc.clientId}\:editForm"
However, I can't get it to work with a custom tag because I don't know of an EL expression (or something) that will give me access to the id. I could probably wait until after the page is loaded, then use jQuery to inspect the id and set the data-target after the fact, but I was hoping for a more pure-JSF solution.
I'm using JSF 2.1 and Bootstrap 2.3, at the moment.
Answer seems to be no. BalusC says you should replace things like custom tags with "normal" JSF components. In this case, that would mean using the composite component.
If you're deadset on using custom tag, I worked around the issue (with lots of help from the answer here) by using an index in the form's id:
I replaced the ui:repeat with a c:forEach that has access to the item's index:
<table>
<c:forEach items="#{bean.items}" var="item" varStatus="status">
<my:editor index="#{status.index}" ... />
</c:forEach>
</table>
And in the custom tag, I used the index in the data-target:
<tr>
<td>#{label}: #{value}</td>
<td>
<a data-target="\#editForm-#{index}" ... ></a>
<h:form id="editForm-#{index}" ... >
...
</h:form>
</td>
</tr>
The only catch is that c:forEach is a build-time construct (see details in this answer), which is a problem if you need any render-time data (like if you build information up in preRenderView). If you do, then you're better off using ui:repeat with a custom component, and relying on the cc.clientId.
I am new to JSF. I have a unordered list and a div.
<ul class="nav navbar-nav">
<li>Test Page</li>
<li>Item1</li>
<li>Item2</li>
<li>item3</li>
</ul>
<div id="content"></div>
Now on click of the list items I want to load different xhtml pages using JSF. Is it possible to achieve this usecase ? I am using JSF 2.0 and primefaces.
Any help will be really appreciated.
Just replace the plain HTML link by a JSF h:link. According to the docs:
Render an HTML "a" anchor element. The value of the component is rendered as the anchor text and the outcome of the component is used to determine the target URL rendered in the "href" attribute.
<li><h:link outcome="TestPage" value="Test Page" /></li>
Where the outcome attribute specifies the target navigation case.
See also:
Implicit navigation in JSF 2
Note that's useful for using JSF navigation cases. If you want to just perform a GET request for an external non-JSF url, just use the plain HTML way.
On click event of <li> element, you can call $('#content').load(Url, successEventHandler)
In my app I have tutor and student as roles of user. And I decide that main page for both will be the same. But menu will be different for tutors and users. I made to .xhtml page tutorMenu.xhtml and student.xhtml. And want in dependecy from role include menu. For whole page I use layout and just in every page change content "content part" in ui:composition.
In menu.xhtml
<h:body>
<ui:composition>
<div class="menu_header">
<h2>
<h:outputText value="#{msg['menu.title']}" />
</h2>
</div>
<div class="menu_content">
<с:if test="#{authenticationBean.user.role.roleId eq '2'}">
<ui:include src="/pages/content/body/student/studentMenu.xhtml"/>
</с:if>
<с:if test= "#{authenticationBean.user.role.roleId eq '1'}">
<ui:include src="/pages/content/body/tutor/tutorMenu.xhtml" />
</с:if>
</div>
</ui:composition>
I know that using jstl my be not better solution but I can't find other. What is the best decision of my problem?
Using jstl-tags in this case is perfectly fine, since Facelets has a corresponding tag handlers (that are processed in the time of view tree creation) for the jstl tags and handles them perfectly. In this case c:if could prevent processing (and adding the components located in the included xhtml file) of the ui:include which leads to reduced component tree and better performance of the form.
One downside of using this approach is that you cannot update these form parts using ajax, i.e. you change the user role and refresh the form using ajax, because the ui:include for the other role is not part of the view anymore. In such case you have to perform a full page refresh.
I have this structure:
WebContent
resources
components
top.xhtml
company
about_us.xhtml
index.xhtml
top.xhtml is a component, that is used in index.xthml and about_us.xhtml too.
top.xhtml
<ul>
<li>Home</li>
<li>About us</li>
...
</ul>
So my problem is, when the current page is index.xhtml the component generates URLs correctly, but when the current page is about_us.xhtml, it generates wrong URLs. I cannot use relative path because it's going to generate the wrong URL too. I think it is because the component is based on the current path of the *.xhtml page.
The only solution I could found out is:
<ul>
<li>Home</li>
<li>About us</li>
...
</ul>
But I think is not 'elegant' at all. Any ideas?
URLs are not resolved based on the file structure in the server side. URLs are resolved based on the real public web addresses of the resources in question. It's namely the webbrowser who has got to invoke them, not the webserver.
There are several ways to soften the pain:
JSF EL offers a shorthand to ${pageContext.request} in flavor of #{request}:
<li>Home</li>
<li>About us</li>
You can if necessary use <c:set> tag to make it yet shorter. Put it somewhere in the master template, it'll be available to all pages:
<c:set var="root" value="#{request.contextPath}/" />
...
<li>Home</li>
<li>About us</li>
JSF 2.x offers the <h:link> which can take a view ID relative to the context root in outcome and it will append the context path and FacesServlet mapping automatically:
<li><h:link value="Home" outcome="index" /></li>
<li><h:link value="About us" outcome="about_us" /></li>
HTML offers the <base> tag which makes all relative URLs in the document relative to this base. You could make use of it. Put it in the <h:head>.
<base href="#{request.requestURL.substring(0, request.requestURL.length() - request.requestURI.length())}#{request.contextPath}/" />
...
<li>Home</li>
<li>About us</li>
(note: this requires EL 2.2, otherwise you'd better use JSTL fn:substring(), see also this answer)
This should end up in the generated HTML something like as
<base href="http://example.com/webname/" />
Note that the <base> tag has a caveat: it makes all jump anchors in the page like relative to it as well! See also Is it recommended to use the <base> html tag? In JSF you could solve it like <a href="#{request.requestURI}#top">top or <h:link value="top" fragment="top" />.
JSTL 1.2 variation leveraged from BalusC answer
<c:set var="baseURL" value="${pageContext.request.requestURL.substring(0, pageContext.request.requestURL.length() - pageContext.request.requestURI.length())}${pageContext.request.contextPath}/" />
<head>
<base href="${baseURL}" />