I'm trying to rerender a couple of components following the upload of a file (a photo) but for some reason, upon completion of the upload, the components are not being rerendered. Could anyone please help?
I'm using Java 1.6 JSF 1.2 Richfaces 3.3.3 Seam 2.2GA on a 64 bit Windows 7 machine running the app in Tomcat 6;
<h:panelGrid columns="2" id="photoGrid"
rendered="#{not signUpAction.fileUpRendered}" styleClass="standard">
<h:graphicImage value="#{signUpAction.imageUrl}" width="150" height="171" />
<a4j:region>
<a4j:commandLink id="remove" action="#{signUpAction.removePhoto}"
reRender="a4jphotoUpload" value="Remove Photo" />
</a4j:region>
</h:panelGrid>
<h:panelGroup id="photoGroup" rendered="#{signUpAction.fileUpRendered}">
<rich:fileUpload maxFilesQuantity="1"
fileUploadListener="#{signUpAction.listener}"
addControlLabel="Add a photo..." allowFlash="true"
id="photoUploadWidget" autoclear="true"
listHeight="1" immediateUpload="true" acceptedTypes="jpg,jpeg,png,gif">
<f:facet name="label">
<h:outputText value="{_KB}KB from {KB}KB uploaded --- {mm}:{ss}" />
</f:facet>
<a4j:support event="onuploadcomplete" reRender="photoGrid,photoGroup"/>
</rich:fileUpload>
</h:panelGroup>
I finally figured out a solution, I call a a4j:jsFunction that rerenders the components and call it from the onuploadcomplete event (see the code below)
<h:panelGroup id="photoGroup" rendered="#{signUpAction.fileUpRendered}">
<rich:fileUpload maxFilesQuantity="1" fileUploadListener="#{signUpAction.listener}"
addControlLabel="Add a photo..."
id="photoUploadWidget" autoclear="true" onuploadcomplete="reloadPhotoPanel()" onfileuploadcomplete="reloadPhotoPanel()"
listHeight="1" immediateUpload="true" acceptedTypes="jpg,jpeg,png,gif">
</rich:fileUpload>
</h:panelGroup>
</a4j:outputPanel>
<a4j:jsFunction id="reloadPhotoPanel" name="reloadPhotoPanel" reRender="photoPanel,photoGrid,photoGroup" />
The problem is that you're trying to rerender a component that isn't rendered the first time the page loaded, this would be the photoGrid component.
In order to make it work, you should wrap the non-rendererd component inside a UIContainer (like <a4j:outputPanel>) that will be always rendered and rerender the bigger container.
<!--
now you will rerender the a4j:outputPanel
and the inner h:panelGrid will appear/dissapear
-->
<a4j:outputPanel id="photoGrid">
<h:panelGrid columns="2"
rendered="#{not signUpAction.fileUpRendered}" styleClass="standard">
<h:graphicImage value="#{signUpAction.imageUrl}" width="150" height="171" />
<a4j:region>
<a4j:commandLink id="remove" action="#{signUpAction.removePhoto}"
reRender="a4jphotoUpload" value="Remove Photo" />
</a4j:region>
</h:panelGrid>
</a4j:outputPanel>
<!--
following the same logic in the h:panelGroup that renders
the rich:fileUpload component
-->
<a4j:outputPanel id="photoGroup">
<h:panelGroup rendered="#{signUpAction.fileUpRendered}">
<rich:fileUpload maxFilesQuantity="1"
fileUploadListener="#{signUpAction.listener}"
addControlLabel="Add a photo..." allowFlash="true"
id="photoUploadWidget" autoclear="true"
listHeight="1" immediateUpload="true" acceptedTypes="jpg,jpeg,png,gif">
<f:facet name="label">
<h:outputText value="{_KB}KB from {KB}KB uploaded --- {mm}:{ss}" />
</f:facet>
<a4j:support event="onuploadcomplete" reRender="photoGrid,photoGroup"/>
</rich:fileUpload>
</h:panelGroup>
</a4j:outputPanel>
Related
When I am using a PrimeFaces p:commandButton
<p:commandButton action=#{bean.action} />
I don't see the the validation messages for inputs (both the default h: ones or the PrimeFaces p: ones.) For example with
<f:validateRequired />
When I am using default command button like
<h:commandButton action=#{bean.action} />
I do see the validations. What can be the cause of this difference?
I am using Prime Faces 3.5 with Mojarra 2.1.18
<h:form id="reliefhourheadcopy-form">
<h:panelGrid columns="1">
<h:outputText value="Kopiere Entlastungsstunden von" />
<h:outputText value="Semester: #{reliefHourHeadManagedBean.reliefHourHead.semester}" />
<h:outputText value="Jahr: #{reliefHourHeadManagedBean.reliefHourHead.year}" />
<h:outputText value="nach" />
</h:panelGrid>
<h:panelGrid columns="3">
<h:outputText value="Semester:" />
<p:selectOneMenu id="semester" value="#{reliefHourHeadManagedBean.semester}">
<f:selectItems value="#{reliefHourHeadManagedBean.semesterTypes}" />
</p:selectOneMenu>
<h:message for="semester" />
<h:outputText for="yearSpinner" value="Jahr:" />
<p:spinner id="yearSpinner" value="#{reliefHourHeadManagedBean.year}" maxlength="4" min="2000" max="2030" size="4">
<f:validateRequired />
<f:validateLongRange minimum="2000" maximum="2030" />
</p:spinner>
<h:message for="yearSpinner" />
</h:panelGrid>
<h:panelGrid columns="1" style="margin-top:25px">
<p:commandButton action="#{reliefHourHeadManagedBean.copyReliefHourHead}" value="Kopieren" icon="ui-icon-copy" >
<f:param name="reliefhourhead_id" value="#{reliefHourHeadManagedBean.reliefHourHeadId}" />
</p:commandButton>
</h:panelGrid>
</h:form>
Like #Partlov wrote in the comments below the question,
Main difference is that p:commandButton is AJAX by default, and h:commandButton is non-AJAX by default.
So
<p:commandButton ... />
is more like
<h:commandButton ...>
<f:ajax/>
</h:commandButton>
but
<p:commandButton ...>
<p:ajax/>
</p:commandButton>
is wrong and leads to undefined behaviour
or the other way around
<h:commandButton ... />
is like
<p:commandButton ajax="false" ... />
The p:commandButton will submit the form by default. However by default it does not update anything in the form after the ajax call is finished so the messages are not displayed (which in development mode would have shown in the log files that messages were enqueued but not displayed) . The non-ajax h:commandButton does a full page refresh that does show the messages. In order to get the form (which contains the message component) updated when using the p:commandButton you need to add the update attribute:
<p:commandButton action="#{reliefHourHeadManagedBean.copyReliefHourHead}" value="Kopieren" icon="ui-icon-copy" update="#form">
<f:param name="reliefhourhead_id" value="#{reliefHourHeadManagedBean.reliefHourHeadId}" />
</p:commandButton>
Adding an (superfluous) f:ajax or p:ajax inside a p:commandXXX can result in strange undefined behaviour
See also
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
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.
I have a p:dialog. My intention is to create a list using p:datagrid and when user clicks an item this dialog will open and show its details. Please consider the example of p:datagrid in the showcase. However, currently it works fine in IE but not in Chrome. If I define "modal=true" then the browser turns black but the dialog doesn't show up.
<p:commandButton update=":form:sharePanel" value="Share" style="font-size: 10px" oncomplete="PF('dlg').show()" rendered="false">
<f:setPropertyActionListener target="#{shareController.current}" value="#{status}" />
</p:commandButton>
<p:dialog widgetVar="dlg" resizable="false" id="sharePanel" styleClass="no-border" modal="true">
<h:outputText value="#{shareController.current.url.url}" />
<h:panelGrid columns="3">
<p:dataGrid value="#{shareController.current.url.NLinkList}" var="nshare" columns="1" rendered="#{shareController.current.url.NLinkList.size() > 0}">
<h:panelGroup styleClass="tag noun">
<h:outputText value="#{nshare.noun}" />
</h:panelGroup>
</p:dataGrid>
<p:dataGrid value="#{shareController.current.url.VLinkList}" var="vshare" columns="1" rendered="#{shareController.current.url.VLinkList.size() > 0}">
<h:panelGroup styleClass="tag verb">
<h:outputText value="#{vshare.verb}" />
</h:panelGroup>
</p:dataGrid>
<p:dataGrid value="#{shareController.current.url.PLinkList}" var="pshare" columns="1" rendered="#{shareController.current.url.PLinkList.size() > 0}">
<h:panelGroup styleClass="tag prep">
<h:outputText value="#{pshare.prep}" />
</h:panelGroup>
</p:dataGrid>
</h:panelGrid>
</p:dialog>
What is wrong here?
If you are using Primefaces versions before 4.0 use dlg.show() instead of PF('dlg').show().
And try appending the dialog in body using attribute appendToBody="true", because if the Facelet is more complex and if you are using Layouts the dialog won't fire ind some browsers only model will appear.
<p:dialog appendToBody="true" >
I would like to submit value form jsf page to bean from overlayPanel with checkbox like this:
To show overlay panel and ajax submission I use this code, and see it's OK in debugger:
<p:commandButton id="joinBtn" value="Basic" type="button" disabled="#{dataPropertyCurrent.notJoinable}"/>
<p:overlayPanel id="joinPanel" for="joinBtn" appendToBody="true" dynamic="false">
<f:facet name="header">Details</f:facet>
<p:dataList value="#{treeBean.getDataPropsCouldBeJoinedWith(dataPropertyCurrent)}" type="definition" var="dataJoinVal">
<h:panelGrid columns="2" cellpadding="10">
<h:column>
<p:selectBooleanCheckbox value="#{dataJoinVal.checked}" id="cbID">
<p:ajax event="change" update="cbID" partialSubmit="true"/>
</p:selectBooleanCheckbox>
</h:column>
<h:column>
<h:outputText value="#{dataJoinVal.caption}" />
</h:column>
</h:panelGrid>
</p:dataList>
<!--<p:commandButton value="Apply" id="btnApplyJoin" type="button" process="#parent" />-->
<h:outputLabel value="ID: #{dataPropertyCurrent.joinDataPropertyId}" />
</p:overlayPanel>
But after it when the overlayPanel is hidden and form submit button being pressed with this code:
<p:commandButton value="Apply join" update="joinAccordionPanel,dsAccordionPanelMain" actionListener="#{treeBean.applyJoinOptions}" />
it sets "false" to bean boolean value again.
So how to submit overlayPanel value to bean properly?
PrimeFaces version: 3.5
I've found explanation here: http://forum.primefaces.org/viewtopic.php?f=3&t=30550#p97737:
"If you are using appendToBody, it's strongly recommended to have a form inside the overlayPanel component that wraps all of the input fields and buttons. This is what you have done in your last solution. However, this means that you cannot place the overlayPanel inside another form in the xhtml page because of the limitation on nesting forms. The best solution is typically to avoid appendToBody wherever it's not absolutely necessary."
Edit
I've added <h:form> inside overlayPanel, and now it works fine:
<p:overlayPanel id="joinPanel" for="joinBtn" appendToBody="true" dynamic="true" >
<h:form id="formTmp">
<f:facet name="header">Details</f:facet>
<p:dataList value="#{treeBean.getDataPropsCouldBeJoinedWith(dataPropertyCurrent)}" type="definition" var="dataJoinVal">
<h:panelGrid columns="2" cellpadding="10">
<h:column>
<p:selectBooleanCheckbox value="#{dataJoinVal.checked}" id="cbID">
<p:ajax event="change" update="cbID" partialSubmit="true"/>
</p:selectBooleanCheckbox>
</h:column>
<h:column>
<h:outputText value="#{dataJoinVal.caption}" />
</h:column>
</h:panelGrid>
</p:dataList>
</h:form>
</p:overlayPanel>
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..