What does <f:facet> do and when should I use it? - jsf

I have been having trouble with the tag <f:facet>. I am working form other examples of code which use it, but I'm not sure exactly what purpose it serves.
I have written some code which in method is exactly the same as other code I have seen which works, except there's is wrapped in a <f:facet name=actions> tag. When I add this around my code the drop down box I am wrapping it around disappears when I deploy. Anyone able to suggest a reason for this or give me an insight into how and when to use facet?
Here is my code, I won't bother adding the bean code as they're just basic getters and setters and I don't think they're causing the trouble.
<f:facet name="actions">
<p:selectOneMenu id="SwitchWeekDrpDwnMenu"
value="#{depotWorkloadBean.selectView}"
partialSubmit="true">
<p:ajax update="mainForm"
listener="#{depotWorkloadBean.updateView}" />
<f:selectItem itemLabel="Day view" itemValue="Day"/>
<f:selectItem itemLabel="01/01/2014" itemValue="Week"/>
</p:selectOneMenu>
</f:facet>
If I remove the facet tag the dropdown box displays, but doesn't function as it should with the beans.

A facet represents a named section within a container component. For example, you can create a header and a footer facet for a dataTable component.
https://web.archive.org/web/20170828020413/http://www.jsftoolbox.com/documentation/help/12-TagReference/core/f_facet.html
It's useful when you want to create component that uses some code from user (let's say wrapper).
ie. when you want to create component that hides long text and shows short version of it. You can use just the element body, but then you will get only one value, if you want to get from user the short AND the long version then you can not do it in one value (without using some discriminant), just use facet and say which one is the long and which is the short version.
<textShortener>
<f:facet name="short">
This text is short.
</f:facet>
<f:facet name="long">
This text is too <b>long</b> to be showed when page loads. User have to click the button after the short text to show this.
</f:facet>
</textShortener>
Yes, this can (and should) be done with jsf templating, but I hope you got it.
To question: you defined facet just in the wild xml, nobody requested it so nobody processed it - that's why it did not throw error nor showed anything.

Related

rich:suggestionbox how to call bean in case user aborts selection

Old SuggestionBox component for RichFaces (version 3.3... yes, I have to maintain legacy code, weep for my fate) is pretty useful, but has one downside.
If user enter some text in input component and then click somewhere else than entry on list of suggestion, partially filled input is left as is. It is ugly and can be confusing, giving impression that something is selected when it is not.
I want to have separate call to bean in this case, allowing me to remove text, if nothing got selected.
Example code:
<h:inputText id="selectorInput" value="#{backingBean.inputText}" label="Select something:" />
<rich:suggestionbox id="suggestion" for="selectorInput" suggestionAction="#{backingBean.resolveSuggestions}" var="sug">
<a4j:support event="onselect" reRender="someForm" action="#{backingBean.select(sug)}" />
<h:column>#{sug.name}</h:column>
</rich:suggestionbox>
I tried to add a4j:support for h:inputText with event="onblur", but it is called before backingBean.select(sug) and has no way to know if something was selected or not, making it almost useless. Adding other events to suggestionbox itself appear to not work at all or even break suggestionbox.
Is there any other way?
The backing JavaScript object has a getSelectedItems() method. It returns an empty array if nothing was selected.
To get the object use
document.getElementById(clientId).component

Equivalent of RichFaces 4 <rich:popupPanel> for RichFaces 3

I am looking for something like <rich:popupPanel> in RichFaces 4, but then for RichFaces 3. I haven't found anything like in documenation. There is only <rich:modalPanel> which doesn't suit my needs, because it has problems displaying my datamodel in table. The selection doesn't work, it always returns no rows selected. If I put my table component in <rich:panel> or <rich:togglePanel>, then it works fine.
Is there any popup window excluding <rich:modalPanel> in RichFaces 3?
I dont have 50 reputation to ask you more details in a comment, so i will answer directly hoping this is what you're asking about.
I think you mean that your problem is that the content of the ModalPanel is not rerendered dynamically. but for this you can wrap your table (or the components you want to update) in an <a4j:outputPanel> with ajaxRendered="true"
Setting ajaxRendered="true" will cause the <a4j:outputPanel> to be updated with each Ajax response for the page, even when not listed explicitly by the requesting component. This can in turn be overridden by specific attributes on any requesting components.
http://docs.jboss.org/richfaces/latest_4_0_X/Component_Reference/en-US/html/chap-Component_Reference-Containers.html#sect-Component_Reference-Containers-a4joutputPanel
In my code I have something like :
<a4j:commandLink id="timelineBtn" action="#{timelineBean.doGenerateLog}"
oncomplete="Richfaces.showModalPanel('timelinePnl');return false;"
value="#{labels['timeline.button.lbl']}"/>
that opens the modalPanel :
<rich:modalPanel style="width:800;height:600;" id="timelinePnl">
<a4j:outputPanel id="dataPanel" ajaxRendered="true">
<!-- your components to be updated go here -->
</a4j:outputPanel>
</rich:modalPanel>
So my content is updated with the results of my timelineBean.doGenerateLog method each time i open the modalPanel .

Displaying read-only forms (values are shown as text instead of disabled input controls) with JSF?

I have a data entry form where user enters lots of data. When user comes to the page to view existing data, the page should be displayed in read-only mode (all values shown as text), when he clicks 'Edit' button, normal form with all input controls should be shown so that user can change and save data.
We are using JSF 2.0 with PrimeFaces library. It is easy to achieve above behavior for text box and text area but not for Checkbox, multi-select, radio,..... controls. Is there any easy way available to achieve above behavior rather than writing our own code (which may run into lot of lines thus making backing bean code ugly)
Thanks for your help...
I'm not sure why you think that you need additional backing bean code for this. You've all the needed values in the backing bean already. Your problem is more in the presentation of those values. Just display them in the desired format by writing the view code accordingly. Perhaps you were thinking it too the hard way.
Instead of a select boolean checkbox, you could display for example a "Yes" or "No" value.
<h:selectBooleanCheckbox value="#{bean.checked}" rendered="#{bean.edit}" />
<h:outputText value="#{bean.checked ? 'Yes' : 'No'}" rendered="#{not bean.edit}" />
Instead of a select one menu/radio, you could just display the value in an output text.
<h:selectOneMenu value="#{bean.selectedItem}" rendered="#{bean.edit}">
<f:selectItems value="#{data.availableItems}" />
</h:selectOneMenu>
<h:outputText value="#{bean.selectedItem}" rendered="#{not bean.edit}" />
Instead of a select many listbox/checkbox, you could just display for example all values comma separated in a loop.
<h:selectManyListbox value="#{bean.selectedItems}" rendered="#{bean.edit}">
<f:selectItems value="#{data.availableItems}" />
</h:selectManyListbox>
<h:panelGroup rendered="#{not bean.edit}">
<ui:repeat value="#{bean.selectedItems}" var="selectedItem" varStatus="loop">
#{selectedItem}#{not loop.last ? ', ' : ''}
</ui:repeat>
</h:panelGroup>
You could wrap it all in a tag file or a composite to minimize boilerplate and code repetition.
I've done this in my last project using composite components which has a "preview" attribute and in the implementation I render a text when this attribute is true and the real (editing) when the attribute is false. For checkbox in preview mode you could show the checkbox itself but disabled, for radio - show the selected item.
MyFaces Tomahawk library [1] contains an extended version of the standard components that adds displayValueOnly attribute for this purpose. This might help you (I haven't used them).
[1] - http://myfaces.apache.org/tomahawk-project/tomahawk20/index.html

<rich:datatable> and <rich:datascroller> problem

I am developing a Seam-Jsfv1.2-EJB3 web app.
I have a datatable and checkboxes in each row. Moreover, I have a datascroller at the bottom of my table as well.
My problem is when I click the next page number from the scroller, the selected checkboxes at the first page of the datatable is gone. I mean, even if they were selected, clicking the next page make them deselected. I see it by going back to the first page again by clicking the scroller.
Do you have any idea about that problem?
In order to clearify my case, I attached my code below:
<rich:dataTable
id="apiV2ProductList" rows="10" var="_apiV2Product"
value="#{apiV2ProductList.resultList}"
rendered="#{not empty apiV2ProductList.resultList}" reRender="ds">
<rich:column>
<f:facet name="header">
<h:selectBooleanCheckbox id="selectionCheckAll" onclick="selectAll()" />
</f:facet>
<h:selectBooleanCheckbox id="selectionCheck" onclick="increase(this)" value="#{_apiV2Product.selectValue}" >
</h:selectBooleanCheckbox>
</rich:column>
...
<f:facet name="footer">
<rich:datascroller id="ds" renderIfSinglePage="false">
</rich:datascroller>
</f:facet>
Many thanks in advance.
Baris
You can extend the org.richfaces.renderkit.html.DatascrollerTemplate
write your own DataScroller for your own styling by adding a component with the below configuration in faces-config.xml
<component>
<component-type>exCustHtmlDatascroller</component-type>
<component-lass>org.jsf.common.ui.EXCustHtmlDatascroller</component-class>
</component>
<render-kit>
<renderer>
<component-family>org.richfaces.Datascroller</component-family>
<renderer-type>exCustDataScrollerTemplate</renderer-type>
<renderer- class>org.jsf.common.ui.EXCustDataScrollerTemplate</renderer-class>
</renderer>
</render-kit>
Adding an a4j support tag between scroller has solved my problem:
<f:facet name="footer">
<rich:datascroller id="ds" renderIfSinglePage="false">
<a4j:support event="onpagechange"/>
</rich:datascroller>
</f:facet>
However the other thing is, I am using JQuery to style my table (ex. on mouse over and out), and this time, when I click the next page of my table, the style is gone.
Any help would be great, many thanks in advance.
**
PS: BTW the wierest thing to my mind is it comes me impossible to find a solution by yourself for this kind of problems. Your creation may not always be enough to solve (at least here in my example, adding a4j:support thing) I am asking experts, how can we handle that kind of things by ourselves...
**
You don't need jQuery for styling the datatable
<rich:dataTable id="dataTable" var="x"
onRowMouseOver="this.style.backgroundColor='#F1F1F1'"
onRowMouseOut="this.style.backgroundColor='#{a4jSkin.tableBackgroundColor}'"
The problem you were seeing with the styles being removed is due to the nature of AJAX, and the way the table is reRendered.
Assuming you were firing the initial styling call based on some form of page onLoad, the first time the page is rendered, your styles will be applied. However, when you click the "next" button with the paginator, you are pulling a lot of new HTML down, and replacing the old HTML in the table with the newer, updated information. The proble you're seeing is that you saw styling because jQuery applied styles to the old nodes, upon reRender, those nodes are completely thrown away, along with their styling. You simply need to figure out the hook to call the "styling" method, and re-execute that call after the table is re-rendered.
Generally, I use an a4j:status tag, and set up the onstart or onstop to re-parse the table.

JSF loop reRender

Hopefully the title isn't too cryptic ...
The problem we have is that we generate a bunch of input controls (h:inputOneMenu, h:inputText etc) from some Java List.
Works fine EXCEPT the requirement is that these inputs validate on the fly. Again not so hard except that as there controls were generated in a loop the only possible reRender action is basically the entire form or an a4j:outputPanel around each loop iteration which is basically the same thing.
Now the above two solutions technically work but they have the nasty side effect of reRendering all the page controls which makes the page feel really twitchy and clunky. We'd like to stop this from happening so ideally the only control that gets reRendered is the control that send the ajax update/validation.
Basically this is our page code:
<ui:repeat value="#{seam-outjected-list}" var="item">
<a4j:outputPanel selfRendered="true">
<h:inputText value=#{item.value}>
<a4j:support event="onblur" ajaxSingle="true" />
</h:inputText>
</a4j:outputPanel>
</ui:repeat>
I've left out a bit of stuff that just renders different controls depending on the item.
As you can see we're currently using the a4j:outputPanel solution so every time any loop generated control is updated all the controls are reRendered.
Thanks in advance if anyone has any thoughts.
My first thought is that you should try replacing your <ui:repeat> with an <a4j:repeat> and take advantage of the ajaxKeys attribute to only reRender certain rows.
From the Richfaces Docs:
The main difference of this component
from iterative components of other
libraries is a special "ajaxKeys"
attribute. This attribute defines row
keys that are updated after an Ajax
request. As a result it becomes easier
to update several child components
separately without updating the whole
page.

Resources