update fields of conditionally rendered form - jsf-2

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>

Related

How to process primefaces dialog

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.

primefaces save on datatable edit not working

my xhtml page. the add functionality works fine. So the converters are working and as ViewScope is not working, I tried SessionScope and it works fine.
<p:commandButton id="addOfficeButton" icon="ui-icon-circle-plus" oncomplete="AddOfficeDialog.show();"/>
<h:form id="officeform">
<p:growl id="growl" showDetail="true" sticky="true" />
<p:dataTable id="officeDT" var="office" value="#{offices}" rowKey="#{office.id}" style="width:40%"
selection="#{officeManagementController.selectedOffice}" selectionMode="single" editable="true">
<p:ajax event="rowSelect" listener="#{officeManagementController.onRowSelect}" oncomplete="editDlg.show()"
update=":tabView:officeform:growl,:tabView:officeform:editPanel"/>
<p:column sortBy="#{office.id}" headerText="Office ID">
<h:outputText value="#{office.id}" />
</p:column>
<p:column headerText="System">
<h:outputText value="#{office.department.name}" />
</p:column>
<p:column headerText="Section">
<h:outputText value="#{office.role.name}" rendered="#{office.role!=null}"/>
</p:column>
<p:column headerText="Options" style="width:50px">
<p:rowEditor></p:rowEditor>
</p:column>
</p:dataTable>
<p:dialog id="AddOfficeDialog" widgetVar="AddOfficeDialog" modal="true" header="Add/Edit Office" hideEffect="fade" showEffect="fade">
<p:outputPanel layout="block" id="officeDetail">
<p:panelGrid columns="2">
<h:outputText value="Systemmm" />
<h:selectOneMenu value="#{officeManagementController.selectedSystem}" converter="#{applicationSystemConverter}">
<f:selectItem itemLabel="Select One" itemValue="#{null}" />
<f:selectItems value="#{departmentss}" var="appdepartment" itemLabel="#{appdepartment.name}" itemValue="#{appdepartment}"/>
<f:ajax event="change" listener="#{officeManagementController.onDepartmentChanged}" render="role"/>
</h:selectOneMenu>
<h:outputText value="Section" />
<h:selectOneMenu id="role" validate="true" value="#{officeManagementController.newOffice.role}" converter="#{departmentSectionConverter}">
<f:selectItem itemLabel="Select One" itemValue="#{null}" />
<f:selectItems value="#{officeManagementController.assignableRoles}" var="role" itemLabel="#{role.name}" itemValue="#{role}"/>
</h:selectOneMenu>
</p:panelGrid>
<p:outputPanel layout="block" style="text-align:center;">
<p:commandButton actionListener="#{officeManagementController.createOffice}" id="addOffice"
value="Add Office" title="Add new office" oncomplete="AddOfficeDialog.hide();" update="growl,officeform"/>
</p:outputPanel>
</p:outputPanel>
</p:dialog>
<p:dialog id="editDlg" widgetVar="editDlg" modal="true" header="Add/Edit Office" hideEffect="fade" showEffect="fade">
<p:outputPanel id="editPanel">
<p:panelGrid columns="2">
<h:outputLabel value="Office ID: " />
<h:outputText value="#{officeManagementController.selectedOffice.id}"/>
<h:outputText value="System" />
<h:selectOneMenu value="#{officeManagementController.selectedOffice.department}" converter="#{applicationSystemConverter}">
<f:selectItem itemLabel="Select One" itemValue="#{null}" />
<f:selectItems value="#{applicationSystems}" var="appdepartment" itemLabel="#{appdepartment.name}" itemValue="#{appdepartment}"/>
<f:ajax event="change" listener="#{officeManagementController.onApplicationSystemChanged}" render="sect"/>
</h:selectOneMenu>
<h:outputText value="Section" />
<h:selectOneMenu id="sect" validate="true" value="#{officeManagementController.selectedOffice.role}" converter="#{departmentSectionConverter}">
<f:selectItem itemLabel="Select One" itemValue="#{null}" />
<f:selectItems value="#{officeManagementController.assignableSysSections}" var="role" itemLabel="#{role.name}" itemValue="#{role}"/>
</h:selectOneMenu>
</p:panelGrid>
<p:outputPanel layout="block" style="text-align:center;">
<h:inputHidden binding="#{officeManagementController.selectedOfficeId}" />
<p:commandButton actionListener="#{officeManagementController.updateOffice()}"
value="Update Office" title="Update office" oncomplete="editDlg.hide();" update="#this,editPanel,growl,officeform"/>
</p:outputPanel>
</p:outputPanel>
</p:dialog>
</h:form>
Backing Bean:
public void updateOffice() {
selectedOffice.setId(Long.valueOf((String)selectedOfficeId.getValue()));
officeManagementService.update(selectedOffice);
facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, CrudStatusMessage.SUCCESS.toString(), "Successfully updated Module: " + selectedOffice.getName()));
}
I am getting the dialog populated with the row values but the issue is onclick of update button, i am getting a Value is not Valid error on dept, but the main thing is the selectedModule's values are not set. Please help. stuck with it since a week.
I think you actually need actionListener (instead of action) on you button. You should read about the differences in API docs but the bottom line is that actionListener will perform an AJAX post-back while action will lead to a redirect (which in turn will destroy your view and replace it with a new one).
Firstly you don't need () in:
<p:commandButton action="#{officeManagementController.updateOffice}" value="Update Office" title="Update office" oncomplete="editDlg.hide();" update="#this,editPanel,growl,officeform"/>
Try using <f:ajax/> in your <h:selectOneMenu> and check if it works.

Primefaces dialog + commandButton

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".

Show/hide JSF2 form using <p:selectBooleanButton>

I need to show and hide component in my JSF 2-PrimeFaces application, please find my code below for the same:
<p:outputLabel for="online_offer" value="Online offer#{msg._question_mark}" styleClass="font-size-1em font-weight-bold input-panel-main" />
<p:panel>
<h:panelGrid columns="1">
<p:selectBooleanButton id="online_offer" value="#{QckPstBen.offer.isExpired}" onLabel="Yes" offLabel="No" onIcon="ui-icon-check" offIcon="ui-icon-close" >
<f:ajax event="click" render="#form" />
</p:selectBooleanButton>
</h:panelGrid>
</p:panel>
<h:outputLabel value=" " />
<h:panelGroup rendered="#{QckPstBen.offer.isExpired}">
<p:outputLabel for="website" value="Website/link to the offer#{msg._colon}" styleClass="font-size-1em font-weight-bold input-panel-main" />
<p:panel>
<h:panelGrid columns="1">
<p:inputText id="website" required="true" size="38" />
<p:watermark for="website" value="www.discountbox.in" />
</h:panelGrid>
</p:panel>
</h:panelGroup>
But it doesnt work, any clue
PrimeFaces components doesn't support <f:ajax>. Use <p:ajax> instead.
<p:selectBooleanButton ...>
<p:ajax update="#form" />
</p:selectBooleanButton>
Note that I omitted the event attribute, it defaults here to click already.
Place rendered on children of <h:panelGroup> instead or place a container of some sort around it, for example p:panel.
This may be OBE by now but...
When referencing the page bean, don't I recall in the #{} context, the convention of using lowercase for class names and method/attributes of the page bean (i.e. not #{QckPstBen.offer.isExpired} but #{qckPstBen.offer.isExpired}?

primefaces inplace query

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>

Resources