Display on/off different areas of HTML - jsf

What I am trying to accomplish is being able to take a section of code / HTML and tell JSF to include it or not in the final render. I have messed around with the <ui:remove> tag, but that will always remove the contents.
Here is what I am trying to not include:
<li><h:commandLink value="Create an Account" action="createUser"/></li>
<li><h:commandLink value="Login" action="login"/></li>
I need something to wrap around this that will include it on a rendered = true/false basis. I want it to not include any bloated code like a div, table, etc.

Hope I understand your question right, have you tried these components with rendered attribute?
Example:
<h:panelGroup rendered="#{bean.display}">
<li><h:commandLink value="Create an Account" action="createUser"/></li>
<li><h:commandLink value="Login" action="login"/></li>
</h:panelGroup>
<h:panelGrid rendered="#{bean.display}">
<li><h:commandLink value="Create an Account" action="createUser"/></li>
<li><h:commandLink value="Login" action="login"/></li>
</h:panelGrid>
<rich:panel rendered="#{bean.display}">
<li><h:commandLink value="Create an Account" action="createUser"/></li>
<li><h:commandLink value="Login" action="login"/></li>
</rich:panel>
'display' is the boolean property defined in your JavaBean which you use to control the visibility of your XHTML code.
Another tag you can use is <ui:include>, it might help you better organize your code when the section of XHTML code is big enough to put in another .xhtml.
<ui:include src="yourPath.xhtml" rendered="#{bean.display}">
</ui:include>
For <ui:remove>, I usually use it to temporarily comment out the code as <!-- XHTML code -->.

Related

JSF Dynamic Breadcrumbs Between Projects

This may be a bit confusing but I will try to be clear.
I have three projects. One is a registry system which stores information shared between the two applications.
Using Application 1 and Application 2 you can access the registry which is supposed to have a bread crumb back to the specific applications home page.
So far what I have is a bean which can determine which app is active and returns the appropriate url for a page requested. Problem is my UI does not accept the url.
<ui:define name="breadcrumbContent">
<h:form id="headerForm">
<ol class="breadcrumb">
<li><h:link value="#{i18n.recordList}" immediate="true"
outcome="#{breadCrumbNavigator.navigatingPage}">
<f:param name="pageToGoTo" value="faces/produceManager/index.xhtml"></f:param>
</h:link></li>
<li><h:link value="#{i18n.businessRegistry}" immediate="true"
outcome="#{breadCrumbNavigator.navigatingPage}">
</h:link></li>
</ol>
</h:form>
</ui:define>
This gives me the two errors
This link is disabled because a navigation case could not be matched.
enter code here
Unable to find matching navigation case from view ID '/produceManager/list.xhtml' for outcome '/ss/faces/index.xhtml'
In the bean I have the URL hard coded. I have tried this with and without the 'localhost:9080' prefix. I am kind of lost on this one. Anyone else do anything like this with breadcrumbs?
Turned out to be really easy!
All I had to do was define a navigation case in the faces config and use command links.
<ui:define name="breadcrumbContent">
<h:form id="headerForm">
<ol class="breadcrumb">
<li><h:commandLink value="#{i18n.recordList}" immediate="true"
action="#{breadCrumbNavigator.getNavigatingPage}">
<f:param name="pageToGoTo" value="goToDashboard"></f:param>
</h:commandLink></li>
<li><h:commandLink value="#{i18n.businessRegistry}" immediate="true"
actions="#{breadCrumbNavigator.navigatingPage}">
<f:param name="pageToGoTo" value="goToProducerManager"></f:param>
</h:commandLink></li>
</ol>
</h:form>
</ui:define>

Show some contents inside p:lightBox

How to show some content inside light-box of primefaces as I have to show some information about the image as no. of likes,no. of comments,and also have to provide option to post comments so on and so forth?
On xhtml page I have written this:
<p:lightBox styleClass="imagebox">
<c:forEach var="event1" items="#{event.files}" varStatus="cnt">
<h:outputLink value="#{listOfFilesForEventBean.getImage854By480ProfileUrl(event1)}" title="#{event1.location.locationName}">
<h:graphicImage value="#{listOfFilesForEventBean.getImageIconProfileUrl(event1)}"/>
</h:outputLink>
</c:forEach>
</p:lightBox>
Where files is list of image profiles that I am iterating.
And I want along with the image which is displayed on lightbox some information about the image should be displayed.
I had similar problem. If somebody is still looking for the answer here is my solution.
I did not find easy way to have some additional controls inside p:lightBox item.
Guess it assigns own JavaScript handlers to all its children and that makes a problem.
Also I had the problems with using commandButton inside ui:repeat. So I'm using my own implementation of p:lightBox and p:remoteCommand to call other actions(like post comments, delete image etc). Something like that:
<p:remoteCommand name="deleteImage" update="imagesGrid"
actionListener="#{imageBean.deleteImage}" />
<h:panelGroup id="imagesGrid">
<ui:repeat var="item" value="#{imageBean.list}">
<div class="docThumbContainer">
<div class="docPlaceholder"></div>
<div class="docThumbImage">
<h:outputLink value="/images?id=#{item.imageId}">
<h:graphicImage value="data:image/jpg;base64,#{item.thumbnail}"
alt="" />
</h:outputLink>
</div>
<div class="docThumbButtons">
<p:commandButton type="button" value="Delete"
onclick="deleteImage([{name:'imageId', value:#{item.imageId}}]);" />
</div>
</div>
</ui:repeat>
</h:panelGroup>
ImageBean:
public void deleteImage(ActionEvent event) {
ImageManager manager = getManager();
manager.deleteImage(StringUtil.parseInt(getUrlParameter("imageId"), -1));
}
Of course it is simplified replacement for p:lightBox. To show the full image in the overlay with prev/next buttons you need additional work. E.g. using p:dialog etc

How to collapse or expand all RichFaces collapsiblePanel elements on the page?

I'm using RichFaces with JSF to develop a simple app. One page of this app contains several collapsiblePanel elements. Some of the collapsiblePanel elements are nested, but never more than a second layer.
I would like to provide links or buttons on the page to expand all and collapse all collapsiblePanel elements on the page. How can I do that?
The elements currently use the switchType="client" attribute to let the client handle the expanding and collapsing. I suspect that using a type of ajax instead may help, but I'm not sure nor do I know how I would take advantage of it.
Update: My question may be easier to understand if I include an example of what I'm trying to do:
<h:form>
<a4j:commandButton actionListener="#{bean.setDefaultExpanded(true)}"
render="reportPanel" value="Expand all" />
<a4j:commandButton actionListener="#{bean.setDefaultExpanded(false)}"
render="reportPanel" value="Collapse all" />
<h:panelGrid id="reportPanel">
<ui:repeat var="account" value="#{bean.results.entrySet().toArray()}">
<rich:collapsiblePanel expanded="#{bean.defaultExpanded}">
<ui:repeat var="chargeGroup" value="#{account.value.entrySet().toArray()}">
<rich:collapsiblePanel expanded="#{bean.defaultExpanded}">
<h:outputText value="content: #{chargeGroup.value}" />
</rich:collapsiblePanel>
</ui:repeat>
</rich:collapsiblePanel>
</ui:repeat>
</h:panelGrid>
</h:form>
The <rich:collapsiblePanel> has the expanded attribute, you can bind it to bean property and control the expansion from there. Something like this
<rich:collapsiblePanel id="panel1" expanded="#{bean.expanded}" …>
<a4j:commandButton actionListener="#{bean.togglePanels()}"
… render="panel1, panel2, …"/>
The switchType controls where the content is pulled from, not how you expand/collapse the panel.
I had the same problem when click individual panels and then expand/collapse all. This work for me (richfaces 4.2.3):
<h:commandButton immediate="true" action="#{controllerBean.toggleMin}" value="collapse all" >
<a4j:ajax render="panel1 panel2"></a4j:ajax>
</h:commandButton>
<h:commandButton immediate="true" action="#{controllerBean.toggleMax}" value="expand all">
<a4j:ajax render="panel1 panel2"></a4j:ajax>
</h:commandButton>
...
<rich:collapsiblePanel id="panel1" immediate="true" expanded="#{modelBean.expanded}" header="Title text" switchType="client">
...
</rich:collapsiblePanel>
...

Single JSF form on a page approach vs several forms?

Does it makes sense to merge these several hidden forms on a single page into just one single big form?
To submit a particular set of parameters belonging to a particular form process attribute could be used to submit all elements required to be processed.
What are the pro/cons of this single form approach over using several forms?
<span class="hiddenForms">
<h:form>
<h:inputHidden id="selctdChnlType_in" value="#{channelCntlr.type}"/>
<h:inputHidden id="selctdChnlId_in" value="#{channelCntlr.channelId}"/>
<p:remoteCommand name="updateChnlDataPanel" process="#form" actionListener="#{channelCntlr.init()}" update=":channelHeader, :channelDataPanel, :channelSideColumn"/>
</h:form>
<h:form>
<h:inputHidden id="selctdLOBId_in" value="#{lobCntlr.targetLOBId}"/>
<p:remoteCommand name="updateLOBPanel" process="selctdLOBId_in, #this" actionListener="#{lobCntlr.retrieveCurrentLOB()}" update=":lobFullContentPanel" />
</h:form>
<h:form id="lobAction_form" >
<h:inputText id="targetLOBId_in" value="#{lobCntlr.targetLOBId}"/>
<h:inputText id="targetResponseId_in" value="#{lobCntlr.targetResponseOrCommmentId}"/>
<h:inputText id="targetAction_in" value="#{lobCntlr.targetAction}"/>
<p:remoteCommand name="doLOBAction" process="targetLOBId_in, targetAction_in, targetResponseId_in,#this" actionListener="#{lobCntlr.doLOBAction()}"/>
<h:inputText id="targetTopics" value="#{lobCntlr.list}" converter="listConverter"/>
<p:remoteCommand name="suggestAsHotLOB" process="targetLOBId_in, targetTopics, #this" actionListener="#{lobCntlr.addForTryAsHotLOB()}"/>
</h:form>
<h:form id="comment_form" >
<h:inputText id="targetLOBId_in" value="#{lobCntlr.targetLOBId}"/>
<h:inputText id="targetCommentOrResponseId_in" value="#{lobCntlr.targetResponseOrCommmentId}"/>
<h:inputText id="comment_in" value="#{lobCntlr.text_input}" required="true">
<f:validateLength minimum="15" maximum="1000"/>
</h:inputText>
<h:inputText id="previousCommenters_in" value="#{lobCntlr.list}" converter="listConverter"/>
<p:remoteCommand name="addComment" process="#form" actionListener="#{lobCntlr.addUserComment()}" oncomplete="addCommentToPage(args);" />
<p:remoteCommand name="deleteComment" process="targetLOBId_in, targetCommentOrResponseId_in, #this" actionListener="#{lobCntlr.removeUserComment()}" oncomplete="removeFromPage(args);" />
</h:form>
<h:form id="recosForm">
<h:inputText id="startFromRecos_in" value="#{recmdnsCntlr.startFromIndex}"/>
<p:remoteCommand name="fetchAllRecos" actionListener="#{recmdnsCntlr.retrieveAllRecmmndns()}" process="startFromRecos_in,howManyRecos_in,isLocalStorAvailble_in,#this" />
<p:remoteCommand name="fetchFollowiesList" actionListener="#{recmdnsCntlr.fetchAllFollowiesList()}" process="#this" oncomplete="storeFollowiesList(args)"/>
</h:form>
<span id="editsForm" style="display:none">
<form action="javascript:void(0);" class="edits_submitter" >
<p:inputTextarea styleClass="editedText"/>
<input type="submit" value="Save edits"/>
<a class="cancel-edit" href="javascript:void(0)">Cancel</a>
</form>
</span>
</span>
A major con to the single, monolithic JSF form control is the sheer volume of data that is (needlessly) sent to the server for processing. Using your existing code. Consider the following. If all the controls in <h:form id="lobAction_form" > and <h:form id="comment_form" > were in a single form, you'd have
<h:inputText id="targetLOBId_in" value="#{lobCntlr.targetLOBId}"/>
<h:inputText id="targetResponseId_in" value="#{lobCntlr.targetResponseOrCommmentId}"/>
<h:inputText id="targetAction_in" value="#{lobCntlr.targetAction}"/>
<p:remoteCommand name="doLOBAction" process="targetLOBId_in, targetAction_in, targetResponseId_in,#this" actionListener="#{lobCntlr.doLOBAction()}"/>
<h:inputText id="targetTopics" value="#{lobCntlr.list}" converter="listConverter"/>
<p:remoteCommand name="suggestAsHotLOB" process="targetLOBId_in, targetTopics, #this" actionListener="#{lobCntlr.addForTryAsHotLOB()}"/>
<h:inputText id="targetLOBId_in" value="#{lobCntlr.targetLOBId}"/>
<h:inputText id="targetCommentOrResponseId_in" value="#{lobCntlr.targetResponseOrCommmentId}"/>
<h:inputText id="comment_in" value="#{lobCntlr.text_input}" required="true">
<f:validateLength minimum="15" maximum="1000"/>
</h:inputText>
<h:inputText id="previousCommenters_in" value="#{lobCntlr.list}" converter="listConverter"/>
<p:remoteCommand name="addComment" process="#form" actionListener="#{lobCntlr.addUserComment()}" oncomplete="addCommentToPage(args);" />
<p:remoteCommand name="deleteComment" process="targetLOBId_in, targetCommentOrResponseId_in, #this" actionListener="#{lobCntlr.removeUserComment()}" oncomplete="removeFromPage(args);" />
</h:form>
For every command action that you initiate in that form, possibly to process 1 input text component, you'd always be sending all 13 components in there to the server anyway. Wasteful and unnecessary. You'll have high volume of client-server communications for small operations and sometimes slow response times. Depending on whatever JSF framework you're using, you might be able to get creative with this situation, selectively processing components and what not, but that is just needless and painful. Clean separation of concerns also comes into play in the presentation layer.
Then there is the problem of validation. More often than not, you will have selected components in a single form that are marked as required and have nothing to do with the rest of the components within that form. You'll most likely be unable to selectively process those components without affecting all the other components on that form.
I see you're using primefaces. You could consider the use of Wizard component. With this component there is a single form with more sections in different tabs. The validation is done in Ajax mode when you go from one tab to the next one. As the partial validation is done with Ajax, only the fields of the tab you are validating, are processed and sent to the server.
It is also useful to split long forms in more readable and user friendly sections.

JSF 2 AJAX - reload whole div (e.g. <ui:include src="toReloadData.xhtml" />)

I'm working with jsf2 and want to use the ajax-functionality of it. Problem: I've already seen some ajax refresh things. But nothing to refresh a whole div...
I have a xhtml page with data from my bean, and i don't really want to refresh all fields of it, it would be easier to refresh the whole ui:include...
does anybody knows a solution? Or do I have to refresh all fields manually?
best regards
Just put them in some container component with an ID and use it in render attribute of f:ajax.
<h:form>
<h:commandButton value="submit" action="#{bean.submit}">
<f:ajax render=":foo" />
</h:commandButton>
</h:form>
<h:panelGroup id="foo" layout="block">
<ui:include src="include.xhtml" />
</h:panelGroup>
Note that <h:panelGroup layout="block"> renders a <div>. If you omit the layout attribute, it defaults to <span> (only whenever there are any attributes which needs to be rendered to HTML, like id).
Okay BalusC, but I'm still having a problem with the includes and ajax.
my index.xhtml includes a search.xhtml and a results.xhtml
the ajax-part is in search.xhtml and the toRender-id is in results.xhtml...
so at rendering the jsf-tags there's the problem that there's no toRender-Id at this time...
EDIT:
Okay the problem was not the arrangement of the includes, it was that the ajax-parts must be in the same form tag like this:
<h:form>
<div id="search" class="search">
<ui:insert name="search" >
<ui:include src="search.xhtml" />
</ui:insert>
</div>
<h:panelGroup id="ajaxResult" layout="block">
<ui:insert name="searchResults" >
<ui:include src="searchResults.xhtml" />
</ui:insert>
</h:panelGroup>
</h:form>
search contains f:ajax tag, ajaxResult is toRenderId
best regards, emre

Resources