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.
Related
I'm trying to conditionally render a <tr> therefore I cannot use <h:panelGroup> as it will render to <span> or <div>
My current (working) approach is the following:
<h:outputFormat rendered="#{negotiator.maySend}">
<tr> my tr stuff </tr>
</h:outputFormat>
This works, but I'm not sure if that's the way to abuse <h:outputFormat> - before that I used <h:outputLabel> but this was rendered to <label> in IE.
I have also read the answers to this question, but as mentioned above, they won't work for me because of the <tr>: How to not render whole block in JSF?
I cannot use <h:panelGroup> as it will render to <span> or <div>
Apparently you didn't test it carefully. The <h:panelGroup> won't render anything if you don't specify attributes which should end up in the client side, like layout, id, styleClass, etc.
Thus, this should technically perfectly work fine.
<h:panelGroup rendered="#{negotiator.maySend}">
<tr> my tr stuff </tr>
</h:panelGroup>
However, better for the main purpose would be to use <ui:fragment>.
<ui:fragment rendered="#{negotiator.maySend}">
<tr> my tr stuff </tr>
</ui:fragment>
This is by the way also possible with <f:verbatim>, but this is deprecated since JSF 2.0 as it's designed specifically for usage in JSP.
See also:
Alternative to ui:fragment in JSF
Conditionally displaying JSF components
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
Ajax update/render does not work on a component which has rendered attribute
I am having a JSF application which creates and presents about 50 reports. These reports are rendered PNGs and under the pictures a table is displayed.
This table uses a RichFaces 4 togglePanel with switchType="client". The togglePanel is just for collapsing and expanding the table.
<h:form>
<rich:togglePanel id="#{param.reportWrapper}_togglePanel"
stateOrder="opened,closed" activeItem="opened" switchType="client">
<rich:togglePanelItem name="closed">
<h:panelGroup>
<div class="myclass">
<ul class="container-icons">
<li>
<h:commandLink styleClass="container-max" value="maximieren">
<rich:toggleControl targetPanel="#{param.reportWrapper}_togglePanel" targetItem="#next" />
</h:commandLink>
</li>
</ul>
<h3>My Heading</h3>
</div>
</h:panelGroup>
</rich:togglePanelItem>
<rich:togglePanelItem name="opened">
<h:panelGroup>
<div class="myclass">
<ul class="container-icons">
<li>
<h:commandLink styleClass="container-min" value="minimieren">
<rich:toggleControl targetPanel="#{param.reportWrapper}_togglePanel" targetItem="#prev" />
</h:commandLink>
</li>
</ul>
<h3>Another Heading</h3>
<div class="scrolling-table-content">
<rich:dataTable>
// ...
</rich:dataTable>
</div>
</div>
</h:panelGroup>
</rich:togglePanelItem>
</rich:togglePanel>
</h:form>
The problem is, that I sometimes get a ViewExpiredExceptions when the reports are loaded. My numberOfLogicalViews and numberOfViewsInSession is 14. I dont want to set it to 50, because of memory issues and because it should not be necessary as only one report is really shown at the same time.
I tried to remove the h:form tags, which are seen as logicalView. In my opinion the togglePanel is not the item, which needs the form because it's switch type is client (not server and ajax, which need form tags). But the command link does need the form tag, because if I remove it, an error occurs saying "this link is disabled as it is not nested within a jsf form".
So I tried to replace the commandLink with a commandButton. This worked fine first and the form wasnt necessary anymore. But somehow the behaviour is completely random now. Sometimes the tables can be expanded, sometimes nothing happens when i click the expand button. When i add form tags again, it works fine, but doesnt solve my ViewExpiredException.
Hope, somebody can help me out here...
Thanks for your help!
Buntspecht
If you only need to switch the panel you can use <a4j:commandLink> that lets you limit the execution scope (so it won't submit the whole form). Or you can remove the command components altogether and just use JavaScript API of the togglePanel:
<a onclick="#{rich:component('panelId')}.switchToItem(#{rich:component('panelId')}.nextItem())">Next</a>
Thank you very much for your help Makhiel. I finally managed to solve the problem with the commandButtons solution. I can't explain why, but the IDs of my togglePanelItems got duplicated in the different reports.
Giving every togglePanelItem a unique ID like
<rich:togglePanelItem name="closed" id="#{param.reportWrapper}_opened">
and
<rich:togglePanelItem name="opened" id="#{param.reportWrapper}_closed">
solved the problem...
So now we got rid of all the h:form tags and thus have about 50 logical views less! :)
I am trying to implement a dynamic menu with JSF2/RichFaces. The idea is simple, the menu is defined in the database, and depends on the connected user.
The menu is correctly generated, but the action is not working, and I don't understand why.
This is my JSF code:
<c:forEach items="${sessionMenu.menus}" var="menu"><!-- Menus -->
<li>
${menu.label}
<ul class="sub-menu" id="sub-${menu.label}">
<c:forEach items="${menu.submenus}" var="submenu"><!-- Sub menus -->
<li>
<a4j:commandLink value="${submenu.label}" action="${sessionMenu.action}"/>
</li>
</c:forEach>
</ul>
</li>
</c:forEach>
${sessionMenu.action} returns a string which should redirect to another page (defined as a navigation-case in the faces-config file).
I also tried to replace the action with a hard-coded string, and it works, I guess that the problem arrives with the EL which is not correctly interpreted.
If some one can help me to understand what is wrong?
Edit:
Here is an example of the links generated:
<a id="mainForm:j_id_g_0_2_0_2" onclick="RichFaces.ajax("mainForm:j_id_g_0_2_0_2",event,{"incId":"1"} );return false;" name="mainForm:j_id_g_0_2_0_2" href="#">Screen</a>
This one was generated dynamically and it does nothing;
<a id="mainForm:j_id_g_0_2_0_4" onclick="RichFaces.ajax("mainForm:j_id_g_0_2_0_4",event,{"incId":"1"} );return false;" name="mainForm:j_id_g_0_2_0_4" href="#">Screen</a>
And this one used a static string and the redirection is working properly.
These 2 links were generated in the same page and on the same request.
Finally, I got it working, I just changed the action value to the method name as it is defined in my bean, that means:
<a4j:commandLink value="#{submenu.label}" action="#{sessionMenu.getAction()}" />
If some one can explain why, I am curious.
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.
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