I'm trying to use primefaces <p:dialog> combined with <p:commandButton>. In my .xhtml page I have a picklist and commandButton which is used to show a dialog. Dialog displays datatable with target values from picklist. Dialog has two buttons: cancel and submit. My problem is that submit button is not fired. What's strange, commandButton out of dialog works.
Here's my .xhtml:
<body>
<ui:composition template="./../resources/mainTemplate.xhtml">
<ui:define name="content">
<h:form>
<p:dialog id="dlg" header="#{messages.chooseSkillLevel}" widgetVar="dlg" modal="true" dynamic="true">
<h:dataTable value="#{editSkills.skillsAndLevels}" var="skillslevel">
<h:column>
#{skillslevel.skill.umiejetnosc}
</h:column>
<h:column>
<p:selectOneMenu value="#{skillslevel.level}" >
<f:selectItems value="#{editSkills.levels}" var="level" itemLabel="#{level.stopien}" itemValue="#{level.id}" />
</p:selectOneMenu>
</h:column>
</h:dataTable>
<p:commandButton value="#{messages.confirm}" action="#{editSkills.showSkillsAndLevels}" oncomplete="dlg.hide();" /> THIS BUTTON IS NOT FIRED
<p:commandButton value="#{messages.cancel}" onclick="dlg.hide()"/>
</p:dialog>
<p:pickList value="#{editSkills.skills}" var="skill" effect="none"
itemValue="#{skill.id}" itemLabel="#{skill.umiejetnosc}"
showSourceFilter="true" showTargetFilter="true" filterMatchMode="contains"
addLabel="#{messages.add}" removeLabel="#{messages.remove}" removeAllLabel="#{messages.removeAll}" >
<f:facet name="sourceCaption">#{messages.skillsList}</f:facet>
<f:facet name="targetCaption">#{messages.yourSkills}</f:facet>
<p:ajax event="transfer" listener="#{editSkills.onTransfer}" />
<p:column style="width:100%;">
#{skill.umiejetnosc}
</p:column>
</p:pickList>
<p:commandButton value="#{messages.confirm}" action="#{editSkills.afterSubmit}" update="dlg" oncomplete="dlg.show()" /> THIS BUTTON WORKS FINE
<p:commandButton value="#{messages.cancel}" action="profile" immediate="true"/>
</h:form>
</ui:define>
</ui:composition>
</body>
I've marked working button and not working one.
What do I have to do to make it working?
You can try either of the following , I vote number one, it's a cleaner design IMO
Bring the <p:dialog/> outside of the general <h:form/> and put an <h:form/> inside it instead
<p:dialog id="dlg" header="#{messages.chooseSkillLevel}" widgetVar="dlg" modal="true" dynamic="true">
<h:form>
<h:dataTable value="#{editSkills.skillsAndLevels}" var="skillslevel">
<h:column>
#{skillslevel.skill.umiejetnosc}
</h:column>
<h:column>
<p:selectOneMenu value="#{skillslevel.level}" >
<f:selectItems value="#{editSkills.levels}" var="level" itemLabel="#{level.stopien}" itemValue="#{level.id}" />
</p:selectOneMenu>
</h:column>
</h:dataTable>
<p:commandButton value="#{messages.confirm}" action="#{editSkills.showSkillsAndLevels}" oncomplete="dlg.hide();" /> THIS BUTTON IS NOT FIRED
<p:commandButton value="#{messages.cancel}" onclick="dlg.hide()"/>
</h:form>
</p:dialog>
Add appendToBody="false" to the <p:dialog/> to ensure the dialog is rendered within the html form in the DOM instead of being auto-relocated to end of HTML body. But this may cause inconsistent rendering in various browsers.
<p:commandButton value="Cancel" oncomplete="PF('yourDialogWidgedVarName').hide();" process="#this" />
Make sure to use ' when u call the widgetVar name. You can also use immediate="true" or process="#this".
Related
I have this button in a form
<p:commandButton process="#this" update=":solution" title="Modify"
actionListener="#{controller.addSolutionAction(registerCause)}"
icon="ui-icon-plus" />
It displays this dialog (it's outside the form)
<p:dialog header="Solutions widgetVar="dlgSolution" id="solution"
showEffect="fade" hideEffect="drop" closable="true" resizable="true" modal="true">
<h:form id="dialog">
<p:pickList id="solutions" var="sol" effect="drop"
itemValue="#{sol}" itemLabel="#{sol.code}" converter="solutionConverter" label="Solutions" >
<f:facet name="sourceCaption">No Seleccionadas</f:facet>
<f:facet name="targetCaption">Seleccionadas</f:facet>
<p:ajax event="transfer" update="#form"
listener="#{controller.handleSolutionChange}" />
<p:column>
<h:outputText id="codeID" value="#{sol.code}" />
</p:column>
<p:column>
<p:commandButton id="button" icon="ui-icon-search" type="button" update="buttonP"/>
<p:overlayPanel id="buttonP" for="button" hideEffect="fade">
<p:editor id="description" required="true"
label="Ver más" width="300" widgetVar="descriptionWidget"
value="#{sol.description}" disabled="true" controls="">
</p:editor>
</p:overlayPanel>
</p:column>
</p:pickList>
<p:outputPanel styleClass="divButton">
<p:growl id="growlMessagePreview" life="2000" />
<p:commandButton icon="ui-icon-close" title="Close" process="#form" update="#form" value="Close" oncomplete="dlgSolution.hide()" />
</p:outputPanel>
</h:form>
</p:dialog>
What I want to do is show the solution's description when I click the button, but it's always empty. I need it to be an editor because the text is formatted
(I tried using a text area but it's empty too), then I put a string but it's not shown. I also used dynamic = "true" in the overlaypanel, it showed the hard coded string but not the value I need.
I'm using Primefaces 3.5. Any suggestions will be welcome, if you need more details, let me know.
I want to retain data in text box while adding/deleting other row.I am using nested datatable. If I click on delete button it refreshed entire datatable, so user lost the partially filled form data.
<h:commandButton id="addBtn" value="Add Value">
<f:ajax listener="#{relationBean.addValue}"
render="datatableIterator" event="click" />
</h:commandButton>
<h:dataTable id="datatableIterator"
value="#{relationBean.datatables}" var="datatable">
<h:column>
<h:dataTable id="relationIterator"
value="#{datatable}" var="item">
<h:column>
<f:facet name="header"> Relation Type Name</f:facet>
<h:outputText value="#{item.relationType}" />
</h:column>
<h:column>
<f:facet name="header">language</f:facet>
<h:outputText value="#{item.languageName}" />
</h:column>
<h:column>
<f:facet name="header"> Value</f:facet>
<h:inputText value="#{item.relationForm}" />
</h:column>
</h:dataTable>
</h:column>
<h:column>
<p:commandLink action="#{relationBean.deleteDataTable}"
immediate="true" update="#form" process="#this" >
<h:graphicImage value="../images/delete.png" />
<f:setPropertyActionListener
target="#{relationBean.deleteId}" value="#{datatable}" />
</p:commandLink>
</h:column>
</h:dataTable>
I got the resolution.
Its only one line change.what I was doing that I was adding the datata before populating the form, so whenever I click on delete button it clears the form. so I added the data after populating the form like this.
getDatatables().add(getRelationDTOList());
before it was
datatables.add(getRelationDTOList());
and included execute="#form" in xhtml add button.
I have a primefaces dialog and what I want to do is process inputtext before commandbutton action starts. Inside myController.sendToPostBox method, myController.rejectionReason string returns null. Here is my view code.When I remove process attribute, commandbutton doesn't works.
<h:form>
....
<p:dialog id="myPanel"
widgetVar="myPanelId"
resizable="true"
appendToBody="true"
draggable="true"
height="200"
width="300">
<p:panelGrid id="myPanelGridId" style="width: 250px;" styleClass="panelGridWithoutBorder">
<p:row>
<p:column colspan="2">
<p:inputTextarea style="width: 250px;" value="#{myController.rejectionReason}"/>
</p:column>
</p:row>
<p:row>
<p:column>
<p:commandButton value="Save"
oncomplete="if (!args.validationFailed) myPanel.hide();"
process="myPanelId"
action="#{myController.sendToPostBox()}"/>
</p:column>
<p:column>
<p:commandButton value="Close" />
</p:column>
</p:row>
</p:panelGrid>
</p:dialog>
</h:form>
Just place the <h:form> inside the dialog (instead dialog inside the <h:form>)
Explanation:
When you use appendToBody="true" you dialog is being transferred outside of the form that wraps it to the body of the generated html , and since there is no form inside the dialog you can't really submit it.
Also take a look at this thread: Proper Construct for Primefaces Dialog
You need something like this:
<h:form id="formDialog">
<p:commandButton id="basic" value="Basic Dialog" onclick="PF('dlg1').show();" type="button" />
</h:form>
<p:dialog id="basicDialog" header="Basic Dialog" widgetVar="dlg1">
<h:form id="formUser">
<h:panelGrid id="grid" columns="2">
<h:outputLabel value="Username:" />
<p:inputText id="user" value="#{user.name}" />
<h:outputLabel value="Password:" />
<p:inputText id="password" value="#{user.password}" />
<h:commandButton value="Login" id="btn" process="#formUser" actionListener="#{user.login}" />
</h:panelGrid>
</h:form>
</p:dialog>
"login" in the actionListener tag is a method in the User(bean) class, that needs the #ManagedBean annotations.
I am using the p:inplace inside a dialog, when i click the dialog for the first time it displays the label (Detail) and on i clicking the label it displays the 2 inputText but if i open the dialog again it displays the 2 inputText without the label (step), how do i ensure that the label is displayed first.
<p:dialog widgetVar="Dialog" header="Update Patient Details" showEffect="clip" hideEffect="clip" modal="true" >
<h:panelGrid id="Details" columns="2">
<p:inplace id="selectableInplace" label="Detail" effectSpeed="fast" event="click">
<h:panelGrid id="innerDetails1" columns="2">
<h:outputLabel value="Name:" />
<p:inputText id="someName" />
<h:outputLabel value="Mobile:" />
<p:inputText id="someMobile" />
</h:panelGrid>
</p:inplace>
</h:panelGrid>
</p:dialog>
The p:inplace element never got any instruction to close.
If you want the p:inplace element to be closed when the dialog is opened you can call the hide() function when the p:dialog closes or when it shows.
I suggest doing this upon closing the dialog. Simply add a widgetVar to the p:inplace, and call it's hide() function in the onHide of the p:dialog.
Working example:
<p:commandButton onclick="Dialog.show()" value="Show" />
<p:dialog widgetVar="Dialog" header="Update Patient Details"
showEffect="clip" hideEffect="clip" modal="true"
onHide="inplace.hide();">
<h:panelGrid id="Details" columns="2">
<p:inplace id="selectableInplace" label="Detail" effectSpeed="fast"
event="click" widgetVar="inplace">
<h:panelGrid id="innerDetails1" columns="2">
<h:outputLabel value="Name:" />
<p:inputText id="someName" />
<h:outputLabel value="Mobile:" />
<p:inputText id="someMobile" />
</h:panelGrid>
</p:inplace>
</h:panelGrid>
</p:dialog>
my problem is, that I want to render form2 conditionally. This collides with a ajax update event of another form1, which should trigger the rendering of form2.
<h:form id="form1">
<h:selectOneMenu id="selectedGroupId" label="#{msgs.group_group}" value="#{groupBean.selectedGroupId}">
<p:ajax event="change" listener="#{groupBean.selectGroupEvent}" update=":form1"/>
<f:selectItems value="#{groupBean.availableGruppen}" />
</h:selectOneMenu>
</h:form>
<h:form id="form2" rendered="#{not empty groupBean.groupDto}">
<p:panelGrid id="groupEditGrid">
...
</p:panelGrid>
</h:form>
Is there a way of doing this without putting the render condition inside a component of form2?
Thanks
Jonny
You cannot update a component that is not on your page. But you could wrap your form in a h:panelGroup that is not rendered contitionally and update the wrapper instead.
Example:
<h:form id="form1">
<h:selectOneMenu id="selectedGroupId" label="#{msgs.group_group}"
value="# {groupBean.selectedGroupId}">
<p:ajax event="change" listener="#{groupBean.selectGroupEvent}"
update=":formWrapper"/>
<f:selectItems value="#{groupBean.availableGruppen}" />
</h:selectOneMenu>
</h:form>
<h:panelGroup id="formWrapper>
<h:form id="form2" rendered="#{not empty groupBean.groupDto}">
<p:panelGrid id="groupEditGrid">
...
</p:panelGrid>
</h:form>
</h:panelGroup>