PrimeFaces Dialog + appendToBody=true not working - jsf

I'm using PF 3.5 and JSF Mojarra 2.1.
I have a dialog which I want to use appendToBody=true. This usually results in "unpredictable behavior" though.
Basically what the dialog does is, when I choose an entry (a persn entity) from a datatable, it gives me filled up input boxes which I can edit, thus editing the particular entry (person details).
Sometimes the input boxes get filled up properly with the entries data. Sometimes they dont.
This behavior does not happen with appendToBody=false.
Aside from that I'm pretty sure there are no nested forms.
As you will notice I am trying out a "One page design" with purely ajax navigation.
Main page (index.xhtml)
<h:body>
<pe:layout id="page" fullPage="true">
<!-- North -->
<pe:layoutPane id="north" position="north" minSize="140"
closable="true" resizable="false">
....
</pe:layoutPane>
<!-- West -->
<pe:layoutPane id="west" position="west" minWidth="150" size="180"
style="font-size: 14px !important;" closable="true"
styleClassHeader="menuBar" resizable="false">
<f:facet name="header">Main Menu</f:facet>
<h:form id="form1">
<p:panelMenu id="panelMenu" style="width: 160px !important">
<!-- On menu click update with Ajax centerpanel and msgPanel -->
<p:submenu label="Persons" style="font-size: 10px ">
<p:menuitem value="Person List" update=":centerpanel"
actionListener="#{layout.setAll('formPersonList.xhtml', 'Person List')}"
action="#{person.init()}">
</p:menuitem>
</p:submenu>
.....
</p:panelMenu>
</h:form>
</pe:layoutPane>
<!-- Center -->
<pe:layoutPane id="content" position="center"
style="font-size: 14px !important" styleClassHeader="menuBar">
<h:panelGroup id="centerpanel" layout="block">
<ui:include id="include" src="#{layout.navigation}" />
</h:panelGroup>
</pe:layoutPane>
</pe:layout>
The dialog is in a file formPersonList.xhtml and is outside the form
<ui:composition ....>
<h:form id="mainForm">
<p:contextMenu for="personTable">
<p:menuitem value="View Details"
process="#form" actionListener="#{person.handleSelectedPerson()}"
update=":dlgPersonGrp"
oncomplete="dlgPerson.show();">
</p:menuitem>
</p:contextMenu>
<p:dataTable id="personTable ....>
....person entities
</p:dataTable>
</h:form>
<p:dialog widgetVar="dlgPerson" showEffect="size"
width="1100" appendToBody="true">
<h:panelGroup id="dlgPersonGrp">
<ui:include src="formPerson.xhtml" />
</h:panelGroup>
</p:dialog>
</ui:composition>
Finally, the form with the input boxes: formPerson.xhtml
<ui:composition ....>
<h:form id ="subForm">
....Input boxes that are supposed to be filled up from a backing bean
and then resubmitted to edit the chosen entry
</h:form>
</ui:composition>
I have tried to dumb it down as much as possible. Let me know if you need more detail.

I know this is a old question, but I was having the same problem with Primefaces 5.
The solution was simple, I've included the attribute appendTo="#(body)" in tag.
<p:dialog header="Title" widgetVar="dlg" modal="true" appendTo="#(body)">
<h:outputText value="Dialog text..." />
<p:commandButton value="Ok" onclick="PF('dlg').close()" />
</p:dialog>

Perhaps the answer is not to use appendToBody. Do you really need it?
One of the common reasons for using appendToBody is to avoid error resulting from putting modal dialogs inside layouts. This workaround, as you've already noted, results in "unpredictable behaviour".
The better way would be just to place the dialog outside the layout.
For more details please see:
http://forum.primefaces.org/viewtopic.php?f=3&t=6154
http://forum.primefaces.org/viewtopic.php?f=3&t=16504

Related

Removing the selections on selectOneListbox / selectManyMenu on a button click in Primefaces

So i have designed a simple form having selectOneListbox / selectManyMenu elements which I am using to generate a piece of text based upon the user selections.
It's working fine. Now what I want is when the user clicks 'clear' button, the selections should be undone and the page should come back to the initial state(no selections).
How can I achieve this ?
xhtml
<h:form>
<h:panelGrid columns="6" style="margin-bottom:10px;" cellpadding="5" columnClasses="label, value">
<p:panel>
<h6 style="width:10.4em;background-color:#ACBECE;">Comment Type</h6>
<!-- comment type -->
<p:selectOneListbox id="basic1" value="#{decisionTreeBean.option1}" style=" font-size: 12px;background-color:silver;width:12em; height:10em; border-style:solid !important;border-width:0.5px !important; border-color:grey !important;">
<f:selectItems value="#{decisionTreeBean.commentType}" var="X" itemLabel="#{X}" itemValue="#{X}" />
</p:selectOneListbox>
</p:panel>
<p:panel>
<h6 style="width:10.4em;background-color:#ACBECE;">MTCN</h6>
<p:selectManyMenu id="advanced1" value="#{decisionTreeBean.option2}" showCheckbox="true" style="font-size: 12px;background-color:silver;width:12em; height:10em; border-style:solid !important;border-width:0.5px !important; border-color:grey !important;">
<f:selectItems value="#{decisionTreeBean.mtcns}" var="X" itemLabel="#{X}" itemValue="#{X}" />
</p:selectManyMenu>
</p:panel>
</h:panelGrid>
<!-- Text Area -->
<p:inputTextarea id="decisionNotes" readonly="#{facesContext.renderResponse}" value="#{decisionTreeBean.decisionNotes}" styleClass="dispostionInputTextArea" autoResize="true">
</p:inputTextarea>
<br/>
<p:commandButton id="generateBtn" value="Generate Text" action="#{decisionTreeBean.generateText}" update=":#{p:component('decisionNotes')}">
</p:commandButton>
<p:commandButton id="clearBtn" value="Clear" action="#{decisionTreeBean.clearText}" update=":#{p:component('decisionNotes')}">
</p:commandButton>
<p:ajaxStatus onstart="PF('statusDialog').show()"
onsuccess="PF('statusDialog').hide()" />
<p:dialog widgetVar="statusDialog" modal="true" draggable="false"
closable="false" resizable="false" showHeader="false">
<p:graphicImage value="/images/ajax-loader.gif" />
</p:dialog>
</h:form>
In my bean, I have a clear method which clears the content of the textarea. I want this button to undo the selections as well as part of the ajax call.
public void clearText() {
this.decisionNotes=" ";
}
(for brevity I have included just 2 columns here in xhtml. There are in total 5 separate selection columns with same functionality)
I would simply reset the values of the Menu/Box in the bean method too:
public void clearText() {
this.decisionNotes=" ";
this.option1 = null;
//and so on...
}
Then you just need to update the components in the update attribute of your button. But I'd update the whole form instead of each component if you want to refresh nearly each component in the form. So just use update="#form":
Note: The default process value of p:commandButton is #form. So your clear button will process the whole form on every click altough it doesn't need to. I'd set it to process="#this", so it will just perform it's action.

Included content is rendered twice even it is excluded with rendered attribute

In a primefaces dialog I show a form with some input fields initially. If the user clicks a button an image or pdf is opened and the dialog is separated with a p:layout. For this I include the rendering of the input fields inside editProperty.xhtml and include it two times in the dialog. Inside a panelGroup to show input fields only and also inside a p:layout. I excluded the panelGroup and the layout with the rendered attribute. So my expectation is that only the dialog is shown with the layout or with the panelgroup.
The initial UI shows it without the p:layout but the fields are rendered twice.
<o:form id="editPropertyFormId">
<p:dialog id="editPropertyDialogId" widgetVar="editPropertyDialogVar" modal="true">
<!-- <c:if test="#{editPropertyContentBL.isContentViewerCollapsed() == false}"> -->
<p:layout id="editPropertiesLayoutId" style="width: 100%; height: 100%;" onResize="adjustContentViewerSize();"
widgetVar="editPropertiesLayoutVar" rendered="#{editPropertyContentBL.contentViewerCollapsed == false}">
<p:layoutUnit id="editPropertiesFieldsLayoutId" position="west" resizable="true" size="400"
style="padding-right: 5px !important;" collapsible="false">
<ui:include src="/sections/edit/editProperty.xhtml">
<ui:param name="idPrefix" value="editPropsInLayout" />
<ui:param name="editPropertyBLInstance" value="#{editPropertyBL}" />
<ui:param name="editPropertyContentBLInstance" value="#{editPropertyContentBL}" />
</ui:include>
</p:layoutUnit>
<p:layoutUnit id="editPropertiesContentViewerLayoutId" position="center" resizable="true"
styleClass="contentViewerLayout">
<ui:include src="/sections/content/contentViewer.xhtml" />
</p:layoutUnit>
</p:layout>
<!-- </c:if> -->
<!-- <c:if test="#{editPropertyContentBL.isContentViewerCollapsed() == true}"> -->
<h:panelGroup rendered="#{editPropertyContentBL.contentViewerCollapsed == true}">
<ui:include src="/sections/edit/editProperty.xhtml">
<ui:param name="idPrefix" value="editProps" />
<ui:param name="editPropertyBLInstance" value="#{editPropertyBL}" />
<ui:param name="editPropertyContentBLInstance" value="#{editPropertyContentBL}" />
</ui:include>
</h:panelGroup>
<!-- </c:if> -->
</p:dialog>
If I use c:if (uncommented in the code), it seems that the ui:parameter does not work because an update inside editProperty.xhtml does not work:
<p:inputText id="#{idPrefix}editPropertyChoiceListValueId"...
<p:commandButton update="#{idPrefix}editPropertyChoiceListValueId"
I get an exception that "editPropseditPropertyChoiceListValueId" cannot be found. Probably there is problem with ui:include/ui:param inside c:if?
Thanks
Oliver
The problem of the twice rendered contents was databinding of a dataTable inside an included xhtml:
<h:dataTable binding="#{editPropertyMainTableBinding}"
I used this to get the current row index:
<ui:param name="curDummyCssClass" value="editPropertyChoiceDummyCssClass#{editPropertyMainTableBinding.rowIndex}" />
After I eliminated this the double rendering was gone. Also the UI rendering seems to be much faster.
Also I removed the "c:if test" and the rendered stuff by putting the contents in separate xhtml files and include it:
<ui:include src="#{editPropertyContentBL.contentViewerCollapsed == true ? '/sections/dialog/editPropertyDialogContent.xhtml' : '/sections/dialog/editPropertyWithContentViewerDialogContent.xhtml'}" />
I don't think this has to do with the double rendering, but removes the unloved c:if tag.

jsf required=true destroys setPropertyActionListener?

Using primefaces 4.0 and jsf 2.2.5
stmt.xhtml has 2 includes. IncludeDetail.xhtml and IncludeDuo.xhtml. IncludeDuo also includes IncludeDetail.
In IncludeDetail.xhtml the <ui:composition> Element owns no <form>, id-Attribute or any other special elements. Only <h:panelGrid>, <h:selectOneMenu> and <h:selectOneMenu>. Nothing special.
IncludeDuo.xhtml owns <p:layout> and <p:message> as child elements of <ui:composition>. Deeper inside the <p:layout> we find this piece of code:
<h:panelGrid columns="1" style="padding-left: 10px">
<h:outputText value="AS" />
<h:selectManyMenu value="#{regelBean.selectedASForNewElement}" required="true" style="height:115px">
<f:selectItems value="#{aSBean.elementList}" var="var" itemLabel="#{var.vaSl}"
itemValue="#{var.vaSl}" />
</h:selectManyMenu>
</h:panelGrid>
If I remove required="true" everything works as expected. If I leave it there, the following setPropertyActionListener won't do it's job anymore:
<h:form id="form1">
<p:dialog header="Neue Regel" widgetVar="newDuoDialog" resizable="false" id="newDuoDlg" showEffect="fade"
hideEffect="fade" modal="true" styleClass="newDialog" width="1220">
<ui:insert name="insertDuo">
<ui:include src="/includes/duoRegelStmt.xhtml" />
</ui:insert>
</p:dialog>
<p:growl id="msgs" showDetail="true" life="20000"/>
<div class="nvg-dataTable">
<p:dataTable id="dt1" var="tVar" value="#{stmtBean.elementList}"
scrollable="false" styleClass="nvg-mainTable" paginator="true"
paginatorAlwaysVisible="false" rows="10"
rowsPerPageTemplate="10,25,100" paginatorPosition="bottom"
currentPageReportTemplate="({startRecord}-{endRecord} von {totalRecords})"
emptyMessage="Keine Statements gefunden" filteredValue="#{stmtBean.filteredElements}">
<p:column styleClass="padding2" style="width:6%">
<p:commandButton value="?" update=":dlgForm"
oncomplete="PF('detDialog').show()" icon="" title="Detail">
<f:setPropertyActionListener value="#{tVar}" target="#{stmtBean.selectedElement}" />
</p:commandButton>
<p:commandButton value="N" update=""
oncomplete="PF('newDuoDialog').show()" icon="" title="Neue Regel mit diesem Statement als Grundlage">
<f:setPropertyActionListener value="#{tVar}" target="#{stmtBean.selectedElement}" />
</p:commandButton>
[ ... ]
Is this a bug or am I misusing sth?
This is expected behaviour: As you are setting the property on submit of the form the property is only set when the form is successfully submitted, which is not the case when validation fails i.e. a required field is empty.
Use process="#this" on the p:commandButton so the form is not submitted. This should work for you as you just want to open the dialog and set the property.

how to refresh referenced part of page with prime faces' p:commandLink?

Environment: Tomcat 6 ,jsf 2.0,prime faces 2.2.1 ,chrome explorer
I want to click the "ViewDetail" link in the left expanded tree and show the product's detail info. But the code below didn't work.
Then I add the attribute ajax="false" to the link, it seems work. But the "p:treeTable" which lies on left part of the page is
also refreshed and collapsed. So how can I do for this: click the link on the left expanded tree node, show the info on the right part
of the page,and keep the left expanded tree node still expanded.
<h:form id="BizTypeTreeTableForm" >
<p:layout fullPage="true">
<p:layoutUnit id="left" position="left" scrollable="true" width="350" resizable="true" closable="false" collapsible="true" minWidth="250" >
<p:treeTable id="BizTypeTreeTable" value="# {treeTableController.root}" var="treeTable">
<p:column>
<f:facet name="header">ProductName</f:facet>
<h:outputText value="#{treeTable.TYPENAME.value }" />
</p:column>
<p:column style="width:5%">
<f:facet name="header">Action</f:facet>
<p:commandLink value="ViewDetail" update="content" action="#{treeTableController.showDetail}">
</p:commandLink>
</p:column>
</p:treeTable>
</p:layoutUnit>
<p:layoutUnit id="center" rendered="true" position="center" style="text-align:left;" scrollable="true" >
<h:outputText value="Please click the left tree node" rendered="# {allTabManager.productObject.TypeNo.value eq null}"/>
<div id="content" class="ui-widget">
<div class="post">
<ui:insert name="content_tab" >...</ui:insert>
</div>
</div>
</p:layoutUnit>
</p:layout>
</h:form>
The update must point to a real JSF component in the tree, not to a plain HTML element.
Replace
<div id="content" class="ui-widget">
by
<h:panelGroup layout="block" id="content" class="ui-widget">
A panelgroup with layout="block" will render a <div> instead of a <span>.
I think your reference to the id is not correct since the div and the p:layout are not the same level.
But you can either try to get the absolute id by using update=":content" or update the whole p:layoutUnit:
<p:commandLink value="ViewDetail"
update="center"
action="#{treeTableController.showDetail}">

JSF - p:tabView - changing tab and previous view still displayed

Inside one tab, I can cilck on a button to display an "h:groupPanel". If I do this, and then change the active tab, the groupPanel that has just appeared is still visible, and appears on top of the now current tab.
The code for the tabView is:
<p:tabView dynamic="true" cache="false" id="characterTabView">
<p:tab title="View" id="viewTab">
<ui:include src="/sections/character/view.xhtml" />
</p:tab>
<p:tab title="Upgrade" id="upgradeTab">
<ui:include src="/sections/character/upgrade.xhtml" />
</p:tab>
</p:tabView>
The "upgrade" page looks like
<h:panelGroup id="searchCompetencies" rendered="#{characterBean.rightPanel == 'searchResult'}">
<h:panelGroup styleClass="characterUpgradeLeft">
<ui:include src="/sections/character/searchViewLeft.xhtml" />
</h:panelGroup>
<h:panelGroup id="competencyCreation" rendered="#{characterBean.rightPanel == 'competencyCreation'}">
<!-- The panel that is made visible -->
</h:panelGroup>
And the page in which the component is made visible (searchViewLeft):
<p:fieldset legend="Create competency" styleClass="createCompetencyStart">
<h:form>
<p:commandButton value="Create competency" type="button" onclick="toggleCreate()" update="upgradeTab" />
</h:form>
</p:fieldset>
where "toggleCreate" changes the value of "characterBean.rightPanel".
Would you have any idea as to what I am missing here?
Thanks a lot :)

Resources