Update components without processing in Primefaces - jsf

I would like to update a component without processing it. I use a binding get the value of a checkbox and decide if the other component should be rendered. Unfortunately, the update? or the binding? doesn't work as i would.
<p:selectBooleanCheckbox id="isPercentage" value="#{myBean.isDiscountInPercentage}"
label="Percentage" binding="#{discountInPercentage}">
<p:ajax process="" update="outpDiscountValue" />
</p:selectBooleanCheckbox>
<p:outputPanel id="outpDiscountValue">
<h:outputLabel value="$" rendered="#{!discountInPercentage.value}" />
<h:outputLabel value="%" rendered="#{discountInPercentage.value}" />
</p:outputPanel>

Related

Primefaces Panels don't update collapsed status after a dialog was dismissed

I'm seeing a strange behaviour with Primefaces (4.0) related to Panels whose collapsed-attributes are bound to a property in a backing bean. Updating the state works fine so the panel collapses/expands correctly when the value of the backing bean changes.
The problem is: I have some p:Dialogs that can be opened to enter some additional/optional information. After closing the dialog, the panel fails to expand/collapse when changing the value. Strangely, other attributes bound to the same property get updated like before.
Example:
XHTML of two panels whose collapsed Attribute is bound to a property. Note that the disabled-attribute of the checkboxes are bound to the same property and still get updated after the dialog is closed.
<p:panel id="panel1" style="width:80%;" toggleable="true" collapsed="#{!bean.panel1.enabled}" widgetVar="panel1Var">
<f:facet name="header">
<p:outputLabel value="Panel1"/>
<p:selectBooleanCheckbox id="p1_enabled" style="margin-left:20px;" disabled="#{bean.panel2.enabled}" value="#{bean.panel1.enabled}">
<f:ajax render="panel1 panel2" />
</p:selectBooleanCheckbox>
</f:facet>
<p:panelGrid columns="2" style="width:100%;" columnClasses="input-col1,input-col2">
<!-- omitted -->
</p:panelGrid>
</p:panel>
<p:panel id="panel2" style="width:80%;" toggleable="true" collapsed="#{!bean.panel2.enabled}" widgetVar="panel2Var">
<f:facet name="header">
<p:outputLabel value="Panel2"/>
<p:selectBooleanCheckbox id="p2_enabled" style="margin-left:20px;" disabled="#{bean.panel1.enabled}" value="#{bean.panel2.enabled}">
<f:ajax render="panel1 panel2" />
</p:selectBooleanCheckbox>
</f:facet>
<p:panelGrid columns="2" style="width:100%;" columnClasses="input-col1,input-col2">
<!-- omitted -->
</p:panelGrid>
</p:panel>
XHTML somewhere else on the same page which opens a dialog:
<p:commandLink id="contactbutton" onclick="PF('contactextended').show();">
<h:outputText value="Extended" />
</p:commandLink>
The dialog is configured like this:
<p:dialog widgetVar="contactextended" modal="true" width="600px" height="500px" showEffect="fade" hideEffect="fade" resizable="false" draggable="false">
The backing bean is a straightforward bean with properties and getters/setter which obviously work. Is there a problem in my implementation? Any ideas how to work around this issue?
Thanks in advance!
Fixed this by myself. The solution seems to be to add process="#this"to the commandLink. I am still not sure what the underlying problem is/was, but at least it doesn't get triggered anymore.

How to update a dynamically generated datatable without touching the rest of the page?

I have a setup in a view, where I display datatables dynamically. That is happening inside a p:accordion-Element, which is generating the tabs dynamically (and therefore the datatables inside).
The user now has the possibility (well, should have..) to add, edit and remove objects to the datatable and therefore to the object that is represented by the tab.
The add- and edit-functions work via dialogs. After successful adding or editing I want to update the datatable containing the data.
If I update the whole accordion-panel I lose the focus on the current tab which is really bad for the user-experience, especially because the other sub-pages of the project always only update the datatable.
After some googling I found out that I can't generate the IDs of JSF-components dynamically, what would make the whole thing a process of minutes.
I also do not have any index I could use to "cheat" and save in my backing-bean when I open the dialog.
I also found out that I could work-around this issue by using JSTL but this is prohibited due to a limited set of allowed languages.
The current setup looks like this:
<p:accordionPanel id="academicYearAccordionPanel"
value="#{academicYearAndClassController.academicYears}"
var="academicYear" multiple="true" dynamic="true" activeIndex="-1"
style="width:100%;">
<p:tab id="academicYear-#{academicYear.academicYear}" title="Jahrgang - #{academicYear.academicYear}">
<p:outputPanel style="float:right">
<p:commandButton value="Löschen" icon="ui-icon-close"
actionListener="#{academicYearAndClassController.setAcademicYear(academicYear)}"
process="#this"
oncomplete="PF('wConfirmAcademicYearDelete').show();">
</p:commandButton>
</p:outputPanel>
<p:spacer style="height:50px;" />
<p:separator />
<!-- Tabcontent -->
<p:outputPanel>
<p:outputPanel style="float:right">
<p:commandButton value="Hinzufügen" icon="ui-icon-plusthick"
actionListener="#{academicYearAndClassController.setAcademicYear(academicYear)}"
process="#this"
oncomplete="PF('wAddSchoolclassDialog').show();">
</p:commandButton>
</p:outputPanel>
<h:panelGrid columns="2">
<h:outputText
value="Klassen des #{academicYear.academicYear}. Jahrgangs" />
<p:spacer style="height:50px;" />
</h:panelGrid>
<p:dataTable emptyMessage="Keine Klassen vorhanden"
id="schoolclassTable"
var="schoolclass"
selection="#{academicYearAndClassController.schoolclass}"
value="#{academicYearAndClassController.getSchoolclasses(academicYear)}"
selectionMode="single" rowKey="#{schoolclass.name}"
scrollable="true" scrollHeight="500">
<p:column headerText="Name">
<h:outputText value="#{schoolclass.identifier}" />
</p:column>
<p:column headerText="Klassenlehrkraft">
<h:outputText
value="#{schoolclass.teacher.name} (#{schoolclass.teacher.symbol})" />
</p:column>
<p:column headerText="Klassenraum">
<h:outputText
value="#{schoolclass.room.name} (#{schoolclass.room.locationName})" />
</p:column>
</p:dataTable>
</p:outputPanel>
</p:tab>
</p:accordionPanel>
I want to update the element with the ID schoolclassTable. How can I achieve this?

Primefaces focus form

<p:inputText value="#{bmiCalculatorBean.height}" update="#form" id="height">
<p:ajax update="#form" />
<f:convertNumber pattern="0" />
</p:inputText>
<p:inputText value="#{bmiCalculatorBean.weight}" update="#form" id="weight">
<p:ajax update="#form" />
<f:convertNumber pattern="0" />
</p:inputText>
I have a problem where after I enter a value into the first inputText and click on the "weight" inputText after a short delay the focus is lost and you need to click on the input box again.
How do I fix this?
This is caused by update="#form" and expected behavior.
In general, just do not update parts which do not need to be updated and update only those which really need to be updated. E.g. only the result calculated so far and the <h|p:message> of the current input:
<p:ajax update="calculatedResult currentInput_message" />
True, this may end up in a boilerplate of IDs in update attribute in large forms. The PrimeFaces Selectors (PFS, supporting jQuery selector syntax in JSF selectors) may then help a lot in this.

Ajax is not always working

below you see some part of my code, i just want to select the first value in a form and the rest should be updated via ajax, for example if you select PK than, MccName, MccVorname,MccDepartment should be shown via ajax after this selection.
This should also be possible in other forms indepently,
<h:panelGrid columns="4">
<h:form id="formmcc10">
<h:outputText value="Pls select PK: " />
<p:selectOneMenu value="#categorymcc.mcccatname}" id="mcccat"
immediate="true" valueChangeListener="#categorymcc.processScat}">
<f:selectItem itemLabel="#categorymcc.mcccatname}"itemValue="" />
<f:selectItems value="#categorymcc.categoryName}" />
<p:ajax update="formmcc10:mccscat1 formmcc10:mccscat2 formmcc10:mccscat3" event="change" />
</p:selectOneMenu><h:outputText value="Mcc Name" />
<p:selectOneMenu value="#{categorymcc.submcccatname}"id="mccscat1">
<f:selectItemsvalue="#{categorymcc.subCategoryName}" />
</p:selectOneMenu>
<h:outputText value="Mcc Vorname" />
<p:selectOneMenu value="#{categorymcc.subsubmcccatname}"id="mccscat2">
<f:selectItems value="#{categorymcc.subSubCategoryName}" />
</p:selectOneMenu>
<h:outputText value="Mcc Department:" />
<p:selectOneMenu value="#{categorymcc.abteilung}" id="mccscat3">
<f:selectItems value="#{categorymcc.abteilungCategoryName}" />
</p:selectOneMenu>
</h:form>
</h:panelGrid>
This could be anything, but I encountered one interesting problem like that recently. I tried to output a bean property like #{myBean.otherBean.name} and it worked when I loaded the page by normal request, but it didn't work with AJAX. When I tried #{myBean.otherBean.id}, it worked in both cases.
The problem was, that backend system didn't fill all data for otherBean on AJAX request, it filled only id (probably for better performance). I had to prepare a getOtherBeanById method and when I called that, AJAX started to work as expected.
I'm not an expert on this field, perhaps someone has a more precise explanation for that.

Reset input fields without executing validation

I have a Facelets view as below:
<h:form id="f1">
<p:panelGrid id="p1" columns="2">
<p: inputText value="Distance Travelled::/><p:inputText value="#{airTransportUsage.distance}" immediate="true"
required="true" requiredMessage="Distance Travelled Field cannot be left blank.."
converterMessage="Distance Travelled must be a number"
validatorMessage="Distance Travelled must be a valid number.."
id="dis">
<f:validateLongRange minimum="1"/>
</p:inputText>
<p:commandButton value="Reset" action="#{airTransportUsage.reset}" update=":f1:p1" />
</p:panelGrid>
</h:form>
When the reset button is clicked, the corresponding method can never be executed due to validation. I can't use immediate="true" on my reset button as it creates some other problems.
The <p:commandButton> processes indeed by default the entire form (process="#form"), you can change this by specifying only the current component in the process attribute.
<p:commandButton value="Reset" ... process="#this" />
However, this will fail if the form is already been validated beforehand. The input fields which have been marked invalid won't be updated with the new model value (which you've resetted yourself). If you're using PrimeFaces 3.4, then embed <p:resetInput> in the button:
<p:commandButton value="Reset" ... process="#this">
<p:resetInput target="#form" />
</p:commandButton>
If you aren't on PrimeFaces 3.4 yet and can't upgrade to it, you can use OmniFaces ResetInputAjaxActionListener for this.
A completely different alternative is to just refresh the current page by a fresh new GET request.
<p:button value="Reset" />
This worked for me in PrimeFaces 5.3
<p:commandButton action="#{bean.reset()}" value="Reset" process="#this" update="#form" resetValues="true" />
You can probably replace the "#form" target of the update attribute to a specific component if you want.

Resources