Can I add/remove Primefaces components dynamically? - jsf-2

How can I add/ remove the primefaces inputText dynamically?

To add/remove textboxes, try the following snippets.
<h:panelGrid columns="1" cellpadding="10">
<h:commandButton value="+" action="#{contactBean.addPhone}"
image="../images/addbtn.png" />
<p:dataTable border="0" value="#{contactBean.phoneNos}" var="p"
rowIndexVar="rowIndex" emptyMessage="No phone numbers entered">
<p:column>
<h:selectOneMenu id="extraTask1" value="#{p.phoneType}">
<f:selectItem itemLabel="Select" itemValue="" />
<f:selectItem itemLabel="Mobile" itemValue="Mobile" />
<f:selectItem itemLabel="Work" itemValue="Work" />
<f:selectItem itemLabel="Others" itemValue="Others" />
</h:selectOneMenu>
</p:column>
<p:column>
<p:inputText value="#{p.phoneNo}" />
</p:column>
<p:column>
<h:commandButton value="remove" image="../images/button_remove.gif"
actionListener="#{contactBean.removePhone}">
<f:param name="columnToRemove" value="#{rowIndex}" />
</h:commandButton>
</p:column>
</p:dataTable>
</h:panelGrid>

This is the easy mode:
<h:inputText rendered="#{object.visibile}" />
if object.visibile == true the inputText is visible.

Related

p:splitButton menuitem with immediate="true" always removes last row of p:dataTable

p:splitButton menuitem for delete functionality with immediate="true" always removes last row of data table even when middle row is deleted it always delete last row. How is this caused and how can I solve it?
The below data table is inside p:wizard and I have to validate data table field values on pressing next button of p:wizard only.
<p:dataTable id="nomineeEducation" var="education" value="#{nominee.prospective.schoolHistoryToSave}" rowIndexVar="status"
rendered="#{fn:length(nominee.prospective.schoolHistoryToSave) > 0}">
<p:column headerText="School" width="250">
<p:selectOneMenu value="#{education.lookupSchoolId}" required="true"
requiredMessage="Education# #{status+1}: Please select School.">
<f:selectItem itemLabel="--School--" itemValue="#{null}" />
<f:selectItems value="#{selectItemList.schoolList}" />
</p:selectOneMenu>
</p:column>
<p:column headerText="Degree Obtained" width="250">
<p:selectOneMenu value="#{education.schoolAffiliations[0].educationId}" required="true"
requiredMessage="Education# #{status+1}: Please select Degree Obtained.">
<f:selectItem itemLabel="--Degree--" itemValue="#{null}" />
<f:selectItems value="#{selectItemList.educationList}" />
</p:selectOneMenu>
</p:column>
<p:column headerText="Dates Attended" width="150">
<p:selectOneMenu value="#{education.underGradMonth}" required="true"
requiredMessage="Education# #{status+1}: Please select Degree Month.">
<f:selectItem itemLabel="--Month--" itemValue="#{null}" />
<f:selectItems value="#{selectItemList.monthList}" />
</p:selectOneMenu>
<p:selectOneMenu value="#{education.underGradYear}" required="true"
requiredMessage="Education# #{status+1}: Please select Degree Year.">
<f:selectItem itemLabel="--Year--" itemValue="#{null}" />
<f:selectItems value="#{selectItemList.yearList}" />
</p:selectOneMenu>
</p:column>
<p:column headerText="Action" width="150">
<p:splitButton value="Select">
<p:menuitem value="Delete" action="#{nominee.deleteEducation(education, false)}" update="nomineeEducation" icon="ui-icon-close" immediate="true"/>
<p:menuitem value="Add New" action="#{nominee.addEducation(false)}" update="nomineeEducation" icon="ui-icon-plus"
rendered="#{fn:length(nominee.prospective.schoolHistoryToSave) eq (status+1)}" />
</p:splitButton>
</p:column>
</p:dataTable>
As said on http://forum.primefaces.org/viewtopic.php?f=3&t=38506, you cannot send data to backing bean if you use immediate="true".
A workaround would be to change your splitButton code for something like:
<p:splitButton value="Select">
<p:menuitem value="Delete"
action="#{nominee.deleteEducation(education, false)}"
update="nomineeEducation"
icon="ui-icon-close"
process="#this"
global="false"
/>
<p:menuitem value="Add New"
action="#{nominee.addEducation(false)}"
update="nomineeEducation"
icon="ui-icon-plus"
rendered="#{fn:length(nominee.prospective.schoolHistoryToSave) eq (status+1)}"
/>
</p:splitButton>

JSF Primefaces - bypass validation in p:ajax [duplicate]

This question already has an answer here:
Skip required validation and invoke the application
(1 answer)
Closed 7 years ago.
I have a p:ajax within a form which triggers on change event in a select. Also I have a separate submit button to submit the form.
The form contains multiple validations. I want to bypass all the validations during the p:ajax call. Instead all the validations should happen during form submission.
This is my form: Field1 and Field2 are mandatory. But these validations should be bypassed during p:ajax call which in turn renders Field3 based on the selected Field2 value.
How can I do this?
<h:body>
<h:form id="formId">
<p:outputPanel autoUpdate="true">
<p:message for="field1Id field2Id" />
<p:panel id="panelId">
<p:panelGrid>
<p:row>
<p:column>
<h:outputText value="Field1:" />
</p:column>
<p:column>
<p:inputText
id="field1Id"
required="true"
requiredMessage="Field1 is Required!"
value="#{testBean.field1}"
size="5"
maxlength="30" />
</p:column>
</p:row>
<p:row>
<p:column>
<h:outputText value="Field2:" />
</p:column>
<p:column>
<p:selectOneMenu
id="field2Id"
value="#{testBean.field2}"
required="true"
requiredMessage="Field2 is Required!">
<f:selectItems
value="#{testBean.fields}"
var="var1"
itemDescription="#{var1.description}"
itemLabel="#{var1.description}"
itemValue="#{var1.id}" />
<p:ajax
process="#form"
event="change" />
</p:selectOneMenu>
</p:column>
</p:row>
<p:row rendered="#{testBean.field2 > 0}">
<p:column>
<h:outputText value="Field3:" />
</p:column>
<p:column>
<p:inputText
value="#{testBean.field3}"
size="5"
maxlength="10" />
</p:column>
</p:row>
</p:panelGrid>
<p:commandButton
value="Save"
action="#{testBean.saveForm()}"
process="#form" />
</p:panel>
</p:outputPanel>
</h:form>
</h:body>
You can achieve by below code. My code just add binding attribute(binding="{save}") at the button, and also change required="true" to required="#{not empty param[save.clientId]}"
<h:body>
<h:form id="formId">
<p:outputPanel autoUpdate="true">
<p:message for="field1Id field2Id" />
<p:panel id="panelId">
<p:panelGrid>
<p:row>
<p:column>
<h:outputText value="Field1:" />
</p:column>
<p:column>
<p:inputText
id="field1Id"
required="#{not empty param[save.clientId]}"
requiredMessage="Field1 is Required!"
value="#{testBean.field1}"
size="5"
maxlength="30" />
</p:column>
</p:row>
<p:row>
<p:column>
<h:outputText value="Field2:" />
</p:column>
<p:column>
<p:selectOneMenu
id="field2Id"
value="#{testBean.field2}"
required="#{not empty param[save.clientId]}"
requiredMessage="Field2 is Required!">
<f:selectItems
value="#{testBean.fields}"
var="var1"
itemDescription="#{var1.description}"
itemLabel="#{var1.description}"
itemValue="#{var1.id}" />
<p:ajax
process="#form"
event="change" />
</p:selectOneMenu>
</p:column>
</p:row>
<p:row rendered="#{testBean.field2 > 0}">
<p:column>
<h:outputText value="Field3:" />
</p:column>
<p:column>
<p:inputText
value="#{testBean.field3}"
size="5"
maxlength="10" />
</p:column>
</p:row>
</p:panelGrid>
<p:commandButton
value="Save"
binding="{save}"
action="#{testBean.saveForm()}"
process="#form" />
</p:panel>
</p:outputPanel>
</h:form>
</h:body>
This approach is proposed by this link.
If you're willing to use omnifaces, there is an ignoreValidationFailed tag.
Check the example at omnifaces showcase:
<o:form>
...
<h:commandButton value="save valid data" action="#{bean.saveValidData}">
<o:ignoreValidationFailed />
<f:ajax execute="#form" />
</h:commandButton>
</o:form>

display a panel after just a select Item

I want to display a panel after just a select Item, I think of that but it give me an error.
Code:
<h:outputText value="* produit" />
<h:selectOneMenu id="produit" value="#{clientMB.selectProduit}">
<p:ajax update="client" listener="#{clientMB.getClientsProduit}" />
<f:selectItem itemLabel="Select One" itemValue="" />
<f:selectItems value="#{produitMB.produits}" noSelectionValue="" var="prod" itemValue="#{prod.refProd}" itemLabel="#{prod.libProd}" />
<f:selectItem itemLabel="Autre" itemValue="" value="lazyload()"/>
</h:selectOneMenu>
<p:outputPanel id="lazypanel" layout="block">
<h:outputText value="This part of page is lazily loaded on demand using a RemoteCommand" rendered="#{requestScope.shouldRender}"/>
</p:outputPanel>
Error:
javax.servlet.ServletException: java.lang.String cannot be cast to javax.faces.model.SelectItem
Solution
<h:outputText value="* produit" />
<h:selectOneMenu id="produit" value="#{clientMB.selectProduit}" onchange="lazyload()">
<p:ajax update="client" listener="#{clientMB.getClientsProduit}" />
<f:selectItem itemLabel="Select One" itemValue="" />
<f:selectItems value="#{produitMB.produits}" noSelectionValue="" var="prod" itemValue="#{prod.refProd}" itemLabel="#{prod.libProd}" />
<f:selectItem itemLabel="Autre" itemValue="" />
</h:selectOneMenu>
<p:outputPanel id="lazypanel" layout="block">
<h:outputText value="This part of page is lazily loaded on demand using a RemoteCommand" rendered="#{requestScope.shouldRender}"/>
</p:outputPanel>
<p:remoteCommand name="lazyload" update="lazypanel">
<f:setPropertyActionListener value="#{true}" target="#{requestScope.shouldRender}" />
</p:remoteCommand>

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.

Dynamically adding new rows in JSF

I have the following code that allows a user enter some data:
<h:panelGrid columns="2" cellspacing="5">
<h:outputLabel value="#{msg.FrequencyOfSpending}" />
<h:selectOneMenu id="ruleFrequencyOptions" value="#{Rule.ruleControls.ControlOne.controlParams.Period.valueSelected}" styleClass="commonSelect">
<f:selectItems value="#{Rule.ruleControls.ControlOne.controlParams.Period.validValues}" itemLabelEscaped="true" />
<f:ajax event="valueChange" listener="#{Rule.ruleControls.ControlOne.controlParams.Period.valueSelectedChange}" onerror="handleAjaxError" render="rulesGroup" />
</h:selectOneMenu>
</h:panelGrid>
<h:panelGroup id="rulesGroup">
<a4j:repeat value="#{Rule.ruleParams.Action.properties}" var="RuleParamProperty" id="budgetRuleIterator">
<h:panelGrid columns="4" cellspacing="5" columnClasses="ruleParamCheckbox, ruleParamAction, ruleParamActionFrequency, ruleParamActionInput">
<h:selectBooleanCheckbox value="#{RuleParamProperty.selected}" immediate="true">
<a4j:ajax event="click" listener="#{RuleParamProperty.selectedChange}" onerror="handleAjaxError" />
</h:selectBooleanCheckbox>
<h:outputText value="#{msg[RuleParamProperty.name]}" />
<h:panelGrid columns="3">
<h:outputText value="#{msg.Action_1}" />
<h:outputText value="#{msg[Rule.ruleControls.ControlOne.controlParams.Period.valueSelected]}" class="italic-text" />
<h:outputText value="#{msg.Action_3}" />
</h:panelGrid>
<h:inputText value="#{RuleParamProperty.inputValue}" />
</h:panelGrid>
</a4j:repeat>
</h:panelGroup>
<!--******* Link here to generate row with exact same format as all code above ***-->
<h:panelGrid columns="2">
<img id="AddIcon" src="#{facesContext.externalContext.requestContextPath}/images/icons/add.png" alt="#{msg.addControl}" />
<h:link value="#{msg.addControl}" />
</h:panelGrid>
I need to add a link to allow them add different variations of this data i.e. user clicks add new control link and a new row appears that allows them enter more data (of the exact same format). They should be able to add multiple rows of the same data.
What is the best way to approach this with JSF2 and Richfaces4?
Should I put my panelGroups within a table?
Thanks
I used a datatable as suggested by Luiggi:
<h:dataTable value="#{rule}" var="currentRuleItem">
<h:column>
<h:panelGrid columns="2" cellspacing="5">
<h:outputLabel value="#{msg.FrequencyOfSpending}" />
<h:selectOneMenu id="ruleFrequencyOptions" value="#{currentRuleItem.ruleControls.ControlOne.controlParams.Period.valueSelected}" styleClass="commonSelect">
<f:selectItems value="#{currentRuleItem.ruleControls.ControlOne.controlParams.Period.validValues}" itemLabelEscaped="true" />
<f:ajax event="valueChange" listener="#{currentRuleItem.ruleControls.ControlOne.controlParams.Period.valueSelectedChange}" onerror="handleAjaxError" render="rulesGroup" />
</h:selectOneMenu>
</h:panelGrid>
<h:panelGroup id="rulesGroup">
<a4j:repeat value="#{currentRuleItem.ruleParams.Action.properties}" var="RuleParamProperty" id="budgetRuleIterator">
<h:panelGrid columns="4" cellspacing="5" columnClasses="ruleParamCheckbox, ruleParamAction, ruleParamActionFrequency, ruleParamActionInput">
<h:selectBooleanCheckbox value="#{RuleParamProperty.selected}" immediate="true">
<a4j:ajax event="click" listener="#{RuleParamProperty.selectedChange}" onerror="handleAjaxError" />
</h:selectBooleanCheckbox>
<h:outputText value="#{msg[RuleParamProperty.name]}" />
<h:panelGrid columns="3">
<h:outputText value="#{msg.Action_1}" />
<h:outputText value="#{msg[currentRuleItem.ruleControls.ControlOne.controlParams.Period.valueSelected]}" class="italic-text" />
<h:outputText value="#{msg.Action_3}" />
</h:panelGrid>
<h:inputText value="#{RuleParamProperty.inputValue}" />
</h:panelGrid>
</a4j:repeat>
</h:panelGroup>
</h:column>
</h:dataTable>
<!--******* Link here to generate row with exact same format as all code above ***-->
<h:panelGrid columns="2">
<img id="AddIcon" src="#{facesContext.externalContext.requestContextPath}/images/icons/add.png" alt="#{msg.addControl}" />
<h:commandLink value="#{msg.addControl}" action="#{myBean.addRule}" />
</h:panelGrid>
// my bean method
public void addRule()
{
iRuleSet.get("RuleControl1").add(createRule());
}

Resources