rich:tooltip does not work in rich:popupPanel - jsf

When I attach rich:tooltip element to any element of the screen of rich:popupPanel, it shows nothing. How can I solve this problem?
<rich:popupPanel id="balancePopup" width="800" resizeable="false"
rendered="true" autosized="true" modal="true"domElementAttachment="body">
<a4j:outputPanel id="balancePanelRegion">
<ui:include src="popup.xhtml" />
</a4j:outputPanel>
</rich:popupPanel>
This doesn't work (popup.xhtml)
<h:inputText value=""
id="my" styleClass="input-medium" readonly="true">
<rich:tooltip id="tooltip"><span>Hint</span></rich:tooltip>
</h:inputText>

Increasing z-index of tooltip component solved the problem:
<rich:tooltip id="tooltip3" style="z-index:10000;">Tooltip</rich:tooltip>

Move rich:tooltip outside:
<h:outputText value="Test"/>
<h:panelGroup id="inputWithTooltip">
<h:inputText />
<rich:tooltip mode="client" layout="block">
<h:outputText value="#{msg.info}" escape="false"/>
</rich:tooltip>
</h:panelGroup>

Related

Bindings in c:forEach

I have a collection of items which each have a min, likely, and max value. There are validators to ensure the maximum is greater than the minimum etc. The validators use bindings so they can compare all three values the user has entered. Originally they were in a ui:repeat, but that was causing trouble with a dropdown and I found switching to a c:forEach fixed it. Unfortunately, it's also messed up the bindings. I'm hoping there's a way to fix them without going back to the ui:repeat.
Is it possible to have a binding in a c:forEach? Is there some way to add an id or a varStatus index to the binding so it isn't the same for every item in the list? e.g. in the example below I've tried things like
<h:inputText id="impactMin_#{impact.id}" binding="#{impactMin_#{impact.id}}">
<h:inputText id="impactMin_#{impact.id}" binding="#{impactMin}_#{impact.id}">
but unsurprisingly, those don't work. If anyone knows a sensible way of doing this, I'd be very grateful to hear it.
This is a simplified version of the code:
<c:forEach id="impacts" var="impact" items="#{mybean.impacts}" varStatus="i">
<h:panelGroup layout="block" id="impactContainer_#{impact.id}">
<h:outputText value="#{impact.score_impact_type_idInterface.score_impact_type_name}"/>
<h:panelGroup layout="block" class="row form-group" id="impactAssessment_#{impact.id}">
<h:panelGroup layout="block">
<h:inputText id="impactMin" value="#{impact.current_impact_min}" binding="#{impactMin}" label="Minimum">
<f:attribute name="impactMl" value="#{impactMl}"/>
<f:attribute name="impactMax" value="#{impactMax}"/>
<f:convertNumber locale="#{loginInfo.realLocale}" minIntegerDigits="1" maxFractionDigits="2" />
<f:validator binding="#{impactMinValidator}"/>
</h:inputText>
</h:panelGroup>
<h:panelGroup layout="block">
<h:inputText id="impactMl" value="#{impact.current_impact_ml}" binding="#{impactMl}" label="Most likely">
<f:attribute name="impactMin" value="#{impactMin}"/>
<f:attribute name="impactMax" value="#{impactMax}"/>
<f:convertNumber locale="#{loginInfo.realLocale}" minIntegerDigits="1" maxFractionDigits="2" />
<f:validator binding="#{impactLikelyValidator}"/>
</h:inputText>
</h:panelGroup>
<h:panelGroup layout="block">
<h:inputText id="impactMax" value="#{impact.current_impact_max}" binding="#{impactMax}" label="Maximum">
<f:attribute name="impactMin" value="#{impactMin}"/>
<f:attribute name="impactMl" value="#{impactMl}"/>
<f:convertNumber locale="#{loginInfo.realLocale}" minIntegerDigits="1" maxFractionDigits="2" />
<f:validator binding="#{impactMaxValidator}"/>
</h:inputText>
</h:panelGroup>
<div class="col-sm-12">
<h:message for="impactMin"/>
<h:message for="impactMl"/>
<h:message for="impactMax"/>
</div>
</h:panelGroup>
</h:panelGroup>
</c:forEach>
While trying to get a better understanding of bindings in general, I found this answer JSF 2 composites and binding for validation . While not quite the same thing, I found it could be adapted to a c:forEach like this:
<c:forEach id="impacts" var="impact" items="#{mybean.impacts}" varStatus="i">
<h:panelGroup layout="block" id="impactContainer_#{impact.id}">
<h:outputText value="#{impact.score_impact_type_idInterface.score_impact_type_name}"/>
<h:panelGroup layout="block" class="row form-group" id="impactAssessment_#{impact.id}">
<ui:param name="impactMin" value="impactMin_#{impact.id}" />
<ui:param name="impactMl" value="impactMl_#{impact.id}" />
<ui:param name="impactMax" value="impactMax_#{impact.id}" />
<h:panelGroup layout="block">
<h:inputText id="impactMin_#{impact.id}" value="#{impact.current_impact_min}" binding="#{requestScope[impactMin]}" label="Minimum">
<f:attribute name="impactMl" value="#{requestScope[impactMl]}"/>
<f:attribute name="impactMax" value="#{requestScope[impactMax]}"/>
<f:convertNumber locale="#{loginInfo.realLocale}" minIntegerDigits="1" maxFractionDigits="2" />
<f:validator binding="#{impactMinValidator}"/>
</h:inputText>
</h:panelGroup>
<h:panelGroup layout="block">
<h:inputText id="impactMl_#{impact.id}" value="#{impact.current_impact_ml}" binding="#{requestScope[impactMl]}" label="Most likely">
<f:attribute name="impactMin" value="#{requestScope[impactMin]}"/>
<f:attribute name="impactMax" value="#{requestScope[impactMax]}"/>
<f:convertNumber locale="#{loginInfo.realLocale}" minIntegerDigits="1" maxFractionDigits="2" />
<f:validator binding="#{impactLikelyValidator}"/>
</h:inputText>
</h:panelGroup>
<h:panelGroup layout="block">
<h:inputText id="impactMax_#{impact.id}" value="#{impact.current_impact_max}" binding="#{requestScope[impactMax]}" label="Maximum">
<f:attribute name="impactMin" value="#{requestScope[impactMin]}"/>
<f:attribute name="impactMl" value="#{requestScope[impactMl]}"/>
<f:convertNumber locale="#{loginInfo.realLocale}" minIntegerDigits="1" maxFractionDigits="2" />
<f:validator binding="#{impactMaxValidator}"/>
</h:inputText>
</h:panelGroup>
<div class="col-sm-12">
<h:message for="impactMin_#{impact.id}"/>
<h:message for="impactMl_#{impact.id}"/>
<h:message for="impactMax_#{impact.id}"/>
</div>
</h:panelGroup>
</h:panelGroup>
</c:forEach>
Note the ui:param bits near the top. That seems to do the trick. Thanks BalusC!

a4j:commandButton doesn't render the element

I've got a JSF page with <rich:tabPanel> which contains 4 tabs.
On the 4th tab I'm trying to use <a4j:commandButton> to execute the action and render resulTable.
Here is the shorten example
<rich:tab header="Journal">
<h:form id="filterForm">
<a4j:jsFunction name="submitByEnter"
action="#{smsLogList.refresh}" render="smsTable" />
<s:div id="divSearch">
<rich:collapsiblePanel header="#{messages['search']}"
switchType="client">
<h:panelGrid column="1">
<s:decorate template="/layout/edit.xhtml">
<ui:define name="label">Package number</ui:define>
<h:inputText id="packNum" style="width:200px"
value="#{smsLogList.packNum}">
<a4j:ajax event="keyup" listener="#{smsLogList.refresh}"
ignoreDupResponses="true" requestDelay="1500"
render="smsTable" />
</h:inputText>
</s:decorate>
<!---some other search elements-->
<s:div styleClass="actionButtons">
<a4j:commandButton id="search" value="#{messages['search']}"
render="smsTable" action="#{smsLogList.go}" />
<a4j:commandButton id="reset" value="#{messages['clear']}"
onclick="document.getElementById('filterForm').reset();"
action="#{smsLogList.clear}" render="divSearch,smsTable" />
</s:div>
</h:panelGrid>
</rich:collapsiblePanel>
</s:div>
<!--- results table-->
<h:panelGrid id="smsTable">
<s:div>
<rich:dataTable value="#{smsLogList.resultList}" var="sms"
id="table" rendered="#{not empty smsLogList.resultList}">
<rich:column>
<f:facet name="header">Type</f:facet>
<h:outputText value="#{sms.smsType}" />
</rich:column>
<!---- some other columns-->
</rich:dataTable>
<rich:dataScroller for="table" />
</s:div>
</h:panelGrid>
</h:form>
</rich:tab>
So, when I'm clicking on the <a4j:commandButton> - nothing happens, but if I'm switching to the other tab and back - the result is as necessary.
I tried to change a4j to <h:commandButton>, but after it's pressed the page switches to the first tab.
Is any solution how to work this out?
The solution is quite simple.
I used <h:form> inside other <h:form>. It will not work anyway. When I remove internal - the jsf works smooth and as it should.

How to submit values in a pop-up panel?

I have bean struggling to understand how to use the rich:popupPanel component in the right way. There are (at least not that I could find) few post about how to use the rich:popupPanel and how to submit values from it.
To make matter worse the panel seams to add (when checking the html) a hard coded "_content" to its component id name (to the div generated). I have tried to use aj4:region tag to partial render the complete form. But that didn't seamed to work, cause nothing where posted to managed bean. So now I have one option left, where the panel has its own form, outside the main one on the page.
I can see that the evaluation of the form (popup) values is happening, but not the execution of the bean function that persist the values (I see the POST request of the command button). The only reason I can think of at the moment, is that the pop-up panel use another bean to persist the values that the main form on the page (both of them are session scoped).
I am thinking of omit the pop-up panel all together, since it seams so hard to make this work. Maybe its a well know secret, since it so few post about it. It behaves the same if if use componentController or only a a4j:commanLink.
How is it possible to submit values from a rich:popupPanel and invoke a backing bean function to persist the pop-up form values ?
Appreciate if someone can shed some light on this, greetings Chris.
I use Richfaces 4.0-final on Glassfish 3.1
<h:form id="main_form">
<!-- Command for popup -->
<a4j:commandLink actionListener="#{userController.prepareCreateSysRequest}" oncomplete="#{rich:component('popup_sys_user_req_form:popup_sys_user_req')}.show(); return false;"
execute="#this" value="Request New Sector/Category" />
...
<a4j:commandButton action="#{projectController.Create}" ...>
</h:form>
<h:form id="popup_sys_user_req_form">
<rich:popupPanel id="popup_sys_user_req" modal="true" autosized="true" resizeable="false">
<f:facet name="header">
<h:outputText value="New Project Request" />
</f:facet>
<f:facet name="controls">
<h:outputLink value="#"
onclick="#{rich:component('popup_sys_user_req')}.hide(); return false;">
X
</h:outputLink>
</f:facet>
<h:panelGrid columns="2">
<h:outputLabel value="Request New:" />
<h:selectOneMenu id="sys_req_type" value="#{userController.selectedSysRequestType}" required="true" requiredMessage="Request Type is required" title="Request Type">
<f:selectItems value="#{userController.getSysRequestTypeItems()}">
</f:selectItems>
</h:selectOneMenu>
<h:outputLabel value="Description:" />
<h:inputTextarea id="user_req_desc" value="#{userController.selectedSysUserRequest.description}" required="true" requiredMessage="Decription is missing" />
</h:panelGrid>
<a4j:commandButton action="#{userController.CreateSysUserRequest}" onclick="#{rich:component('popup_sys_user_req')}.hide(); return false;" execute="#form" render="popup_sys_user_req_form" value="Send Request" />
</rich:popupPanel>
</h:form>
For what I have done I used to have the issue to got to submit twice only the first time.
To fix it the form got to be outside the popupPane. And also that the popupPanel should have the attibute domElementAttachment="form".
Example.
<h:form>
<rich:popupPanel id="shipmentItemUpdateDialog"
autosized="true"
domElementAttachment="form">
<f:facet name="header">
<h:panelGroup>
<h:outputText value="#{shipmentBundle.shipmentItemDetailsHeader}" />
</h:panelGroup>
</f:facet>
<f:facet name="controls">
<h:commandLink>
<h:graphicImage value="/core/images/modal/close.png"/>
<rich:componentControl target="shipmentItemUpdateDialog" operation="hide" />
</h:commandLink>
</f:facet>
<h:outputText for="shipmentItemName"
value="#{coreBundle.requiredChar} #{shipmentBundle.shipmentItemName}"
/>
<h:inputText id="shipmentItemName"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.name}"
label="#{shipmentBundle.shipmentItemName}"
size="40" >
</h:inputText>
<h:outputText for="shipmentItemCode"
value="#{coreBundle.requiredChar} #{shipmentBundle.shipmentItemCode}"
/>
<h:inputText id="shipmentItemCode"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.code}"
label="#{shipmentBundle.shipmentItemCode}"
size="40" >
</h:inputText>
<h:outputText value="#{coreBundle.requiredChar} #{shipmentBundle.shipmentItemAmount}"
/>
<h:inputText id="shipmentItemAmount"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.amount}"
label="#{shipmentBundle.shipmentItemAmount}"
size="4" >
<f:validateLongRange minimum="1"/>
</h:inputText>
<h:outputText value="#{coreBundle.requiredChar} #{shipmentBundle.shipmentItemNeedsCooling}"
/>
<h:selectBooleanCheckbox id="shipmentItemNeedsCooling"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.needsCooling}"
label="#{shipmentBundle.shipmentItemNeedsCooling}"
/>
<h:outputText for="shipmentItemDetails"
value="#{shipmentBundle.shipmentItemDetails}"
/>
<h:inputTextarea id="shipmentItemDetails"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.details}"
label="#{shipmentBundle.shipmentItemDetails}"
cols="38"
rows="5"
/>
</h:panelGrid>
<h:panelGrid columns="1" dir="LTR">
<h:panelGrid columns="2" dir="LTR">
<a4j:commandButton value="#{coreBundle.acceptButton}"
action="#{shipmentItemController.onUpdate()}"
render="shipmentItemsTable">
</a4j:commandButton>
<h:commandLink value="#{coreBundle.closeLink}"
immediate="true">
<rich:componentControl target="shipmentItemUpdateDialog" operation="hide" />
</h:commandLink>
</h:panelGrid>
<h:outputText value="#{coreBundle.requiredText}"/>
</h:panelGrid>
</rich:popupPanel>
</h:form>
I hope this helps.
I think you got it right.. think of the pop-up as a regular page. To submit and close the pop-up, do something like this:
<a4j:commandButton value="Save" onclick="#{rich:component('panelId}.hide();" render="..."/>
Hope this helps..

rich:suggestionbox submits partial string

I use jsf 1.2, richfaces 3.3.2 .
For some reason my suggestionbox submits the value i typed (a.k.a suggestion string) and not what i clicked in the suggested list that opens. How do i fix this?
<h:panelGroup>
<a4j:region renderRegionOnly="false" >
<h:panelGrid columns="2" border="0" cellpadding="0" cellspacing="0">
<h:inputText value="#{ManualReportControl.street}" id="streetNames" style="width:120px;" >
<a4j:support event="onchange" reRender="streetGis" ></a4j:support>
</h:inputText>
<h:graphicImage value="/images/icons/arrow.png"
onclick="#{rich:component('suggestionBoxStreet')}.callSuggestion(true)"
alt="" />
</h:panelGrid>
<rich:suggestionbox id="suggestionBoxStreet" for="streetNames"
suggestionAction="#{ManualReportControl.autocomplete}"
var="street"
minChars="2" >
<h:column>
<h:outputText value="#{street}" />
</h:column>
</rich:suggestionbox>
</a4j:region>
</h:panelGroup>
Got it!
I moved a4j:support from inputText to suggestionBox and now it works.
The code:
<h:panelGroup id="streetNames">
<a4j:region renderRegionOnly="false" >
<h:panelGrid columns="3" border="0" cellpadding="0" cellspacing="0">
<coral:inputString value="#{ManualReportControl.street}" id="streetName" style="width:120px;" tabindexreal="13"/>
<h:graphicImage value="/images/icons/arrow.png"
onclick="#{rich:component('suggestionBoxStreet')}.callSuggestion(true)"
alt="" />
</h:panelGrid>
<rich:suggestionbox id="suggestionBoxStreet" for="streetName"
suggestionAction="#{ManualReportControl.autocomplete}"
var="street"
minChars="2" selfRendered="true" >
<h:column>
<h:outputText value="#{street}" />
</h:column>
<a4j:support event="onselect" reRender="streetGis" ></a4j:support>
</rich:suggestionbox>
</a4j:region>
</h:panelGroup>
Probably happening because onchange event is fired before the selection is made.

Cannot 'hide' rich:fileUpload

Im trying to create a page that uses the rich:fileUpload, to (surprisingly) upload an image, once the upload is completed I want to 'hide' the rich:fileUpload component and display the jQuery plugin jCrop so that the image can be cropped before saving. once the image is saved from the crop selected, the two components should toggle their viewability again.
However, I dont appear to be able to get the rich:fileUpload to 'hide'. the jCrop component displays fine, as does the jCrop functionality. but no matter what I try rich:fileUpload is still displayed on the screen. Actually if I add rendered="#{!uploadAndCrop.newImage}" to the rich:panel that the rich:fileUpload is in, nothing seems to update. I have to remove this for the jCrop component to appear.
My code is below, it is a little messy as ive tried so many different things. Would be extremely grateful if someone could point me in the right direction with this, or advise a better way of doing it.
Thanks
<ui:define name="head">
<link href="stylesheet/jquery.Jcrop.css" rel="stylesheet"
type="text/css" />
<script type="text/javascript" src="scripts/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="scripts/jquery.Jcrop.js"></script>
<script language="Javascript">// <![CDATA[ //
{
var $J = jQuery.noConflict();
}
//]]> //</script>
</ui:define>
<ui:define name="body">
<h:form>
<h:panelGrid columns="2" columnClasses="top,top">
<h:panelGroup id="uploadgroup">
<a4j:outputPanel id="uploadpanel">
<rich:panel rendered="#{!uploadAndCrop.newImage}">
<rich:fileUpload fileUploadListener="#{uploadAndCrop.listener}"
maxFilesQuantity="#{uploadAndCrop.uploadsAvailable}" id="upload"
immediateUpload="#{uploadAndCrop.autoUpload}"
acceptedTypes="jpg, gif, png, bmp"
allowFlash="#{uploadAndCrop.useFlash}" listHeight="80px">
<ui:remove>
onfileuploadcomplete="Richfaces.showModalPanel('croppanel');">
</ui:remove>
<a4j:support event="onuploadcomplete"
reRender="info, uploadgroup, cropgroup" />
</rich:fileUpload>
<h:outputText value="#{uploadAndCrop.newImage}" id="newimage" />
<a onclick="Richfaces.showModalPanel('croppanel');" href="#">Show
ModalPanel</a>
</rich:panel>
</a4j:outputPanel>
</h:panelGroup>
<h:panelGroup id="info">
<rich:panel bodyClass="info" rendered="#{!uploadAndCrop.newImage}">
<f:facet name="header">
<h:outputText value="Uploaded Image Preview" />
</f:facet>
<rich:dataGrid columns="1" value="#{uploadAndCrop.files}"
var="file" rowKeyVar="row">
<rich:panel bodyClass="rich-laguna-panel-no-header">
<h:panelGrid columns="2">
<a4j:mediaOutput element="img" mimeType="#{file.mime}"
createContent="#{uploadAndCrop.paint}" value="#{row}"
style="width:156x; height:71px;" cacheable="false">
<f:param value="#{uploadAndCrop.timeStamp}" name="time" />
<s:conversationId />
</a4j:mediaOutput>
</h:panelGrid>
</rich:panel>
</rich:dataGrid>
</rich:panel>
<rich:spacer height="3" />
<br />
<a4j:commandButton action="#{uploadAndCrop.clearUploadData}"
reRender="info, upload" value="Clear Uploaded Image" />
</h:panelGroup>
<h:panelGroup id="cropgroup">
<rich:panel rendered="#{uploadAndCrop.newImage}">
<f:facet name="header">
<h:outputText value="Crop Image" />
</f:facet>
<a4j:outputPanel id="crop" layout="inline">
<rich:jQuery selector="#cropbox" timing="immediate"
query="Jcrop()" />
<a4j:mediaOutput element="img"
mimeType="#{uploadAndCrop.tempImageStore.mime}" id="cropbox"
createContent="#{uploadAndCrop.paintCrop}" value="null"
style="width:312; height:142px;" cacheable="false">
<f:param value="#{uploadAndCrop.timeStamp}" name="time" />
<s:conversationId />
</a4j:mediaOutput>
<rich:spacer height="3" />
<br />
<a4j:commandButton action="#{uploadAndCrop.clearUploadData}"
reRender="info, upload" value="Crop" />
</a4j:outputPanel>
</rich:panel>
</h:panelGroup>
</h:panelGrid>
<h:commandButton id="save" value="Save"
action="#{uploadAndCrop.save}">
<f:param name="cmsCompanyIdCom" value="" />
</h:commandButton>
<s:button id="cancelEdit" value="Cancel" propagation="end"
view="/CmsCompany.xhtml">
<f:param name="cmsCompanyIdCom" value="" />
</s:button>
</h:form>
<ui:remove>
<rich:modalPanel id="croppanel" width="350" height="240">
<f:facet name="header">
<h:panelGroup>
<h:outputText value="Crop Image"></h:outputText>
</h:panelGroup>
</f:facet>
<f:facet name="image">
<ui:remove>
<h:panelGroup>
<h:outputText value="close" />
<rich:componentControl for="croppanel" attachTo="close"
operation="hide" event="onclick" />
</h:panelGroup>
</ui:remove>
</f:facet>
<rich:panel rendered="#{uploadAndCrop.newImage}">
<ui:remove>
<f:facet name="header">
<h:outputText value="Crop Image" />
</f:facet>
</ui:remove>
<a4j:outputPanel id="crop" layout="inline">
<a4j:mediaOutput element="img"
mimeType="#{uploadAndCrop.tempImageStore.mime}" id="cropbox"
createContent="#{uploadAndCrop.paintCrop}" value="null"
style="width:312; height:142px;" cacheable="false">
<f:param value="#{uploadAndCrop.timeStamp}" name="time" />
<s:conversationId />
</a4j:mediaOutput>
<ui:remove>
<rich:spacer height="3" />
<br />
<a4j:commandButton action="#{uploadAndCrop.clearUploadData}"
reRender="info, upload" value="Crop" />
</ui:remove>
</a4j:outputPanel>
</rich:panel>
<a onclick="Richfaces.hideModalPanel('croppanel');" href="#">Hide
ModalPanel</a>
</rich:modalPanel>
</ui:remove>
</ui:define>
I dont know how is your uploadAndCrop.newImage method, but you can just use a boolean and sets it to false on the fileUploadListener.
But reRender the <a4j:outputPanel id="uploadpanel">, not the <rich:fileUpload> or the group.
<a4j:outputPanel id="uploadpanel" rendered="#{bean.fileUpRendered}">
(...)
<rich:fileUpload...
<a4j:support event="onuploadcomplete"
reRender="info, uploadpanel, cropgroup" />
</rich:fileUpload>
(...)
</a4j:outputPanel>
Bean:
Boolean fileUpRendered;
(...)
public void listener(UploadEvent event) throws Exception {
try {
(...)
fileUpRendered = false;
catch (...) { (...) }
}
//Get set
public get/set fileUpRendered() { }...

Resources