Primefaces7: How to use formular inputs as function parameters - jsf

I want to implement a login-functionality using user-input directly (w/o variables in handling bean).
After migrating to Primefaces, the xhtml-code code does not work anymore.
<h:form>
...
<h:outputLabel for="mail" value="Email:" />
<p:inputText id="mail" value="#{mail}" required="true"/>
<h:outputLabel for="password" value="Passwort:" />
<p:password id="password" value="#{password}" required="true"/>
<p:commandButton value="Anmelden" update="loginGrowl" action="#{user.login(mail.value,password.value)}"/>
...
</h:form>
It gives the error:
WARNUNG: #{user.login(mail.value,password.value)}: javax.el.PropertyNotFoundException: /index.xhtml #43,122 action="#{user.login(mail.value,password.value)}": Property [value] not found on type [java.lang.String]

It turned out that 'mail' and 'password' actually ARE the input strings.. So the following will work (JSF 2.3; PrimeFaces 7.0):
<h:form>
<h:outputLabel for="mail" value="Email:" />
<p:inputText id="mail" value="#{mail}" required="true"/>
<h:outputLabel for="password" value="Passwort:" />
<p:password id="password" value="#{password}" required="true"/>
<f:facet name="footer">
<p:commandButton value="Anmelden" action="#{user.login(mail,password)}"/>
</f:facet>
</h:form>
I don't know when they changed it and I can't find anything documented so I'll leave the question here answered by myself for anyone who might stumble around.

Related

<p:dataScroller> reloading automatically on entity edits

I have a p:datascroller configured to display a list of entities and lazy loading them upon clicking the more button.
<h:form id="investigationOperationsForm">
<p:dataScroller
value="#{investigationManagerBackingBean.lazyLoadedInvestigationOperations}"
var="investigationOperation" chunkSize="9" lazy="true"
rowIndexVar="test">
<f:facet name="header">
Scroll down to load investigations
</f:facet>
<h:panelGrid columns="2" style="width:100%"
columnClasses="logo,detail">
<p:commandLink oncomplete="PF('investigationDialogW').show()"
update="investigationEditorForm" immediate="true">
<f:setPropertyActionListener value="#{investigationOperation}"
target="#{investigationManagerBackingBean.selection}" />
<p:graphicImage alt="Investigation Operation"
url="/images/common/investigation-operation.png" />
</p:commandLink>
<!-- h:outputText value="#{investigationOperation.name}" /-->
<p:outputPanel id="pnl">
<h:panelGrid columns="2" cellpadding="5">
<h:outputText value="Name:" />
<h:outputText value="#{investigationOperation.name}"
style="font-weight: bold" />
<h:outputText value="Description:" />
<h:outputText value="#{investigationOperation.shortDescription}"
style="font-weight: bold" />
</h:panelGrid>
<p:draggable for="pnl" />
</p:outputPanel>
</h:panelGrid>
<f:facet name="loader">
<p:outputPanel
visible="#{investigationManagerBackingBean.lazyLoadedInvestigationOperations.rowCount gt 10}"
rendered="#{investigationManagerBackingBean.lazyLoadedInvestigationOperations.rowCount gt 10}">
<p:commandLink value="More" />
</p:outputPanel>
</f:facet>
</p:dataScroller>
</h:form>
In addition, I have a dialog that pops up when the p:commandLink oncomplete method is executed where I can update the value of the current selection and persist the changes.
<p:dialog id="investigationDialog"
header="#{msg['inv-manager.invDialog.header.title']}"
widgetVar="investigationDialogW" minWidth="400" minHeight="400"
resizable="false" position="center center" modal="true">
<p:panel id="investigationEditorPanel">
<h:form id="investigationEditorForm">
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel for="name"
value="#{msg['inv-manager.invDialog.nameFieldLabel']}" />
<p:inplace id="nameInplaceEditor" editor="true">
<p:inputText
value="#{investigationManagerBackingBean.selection.name}"
id="name" required="true" immediate="true"
label="#{msg['inv-manager.invDialog.nameFieldInputLabel']}" />
</p:inplace>
<h:outputLabel for="shortDescription"
value="#{msg['inv-manager.invDialog.shortDescriptionFieldLabel']}" />
<p:inplace id="shortDescriptionInplaceEditor" editor="true">
<p:inputText
value="#{investigationManagerBackingBean.selection.shortDescription}"
id="shortDescription" required="true" immediate="true"
label="#{msg['inv-manager.invDialog.shortDescriptionFieldInputLabel']}" />
</p:inplace>
<h:outputLabel for="description"
value="#{msg['inv-manager.invDialog.descriptionFieldLabel']}" />
<p:inputTextarea id="description" required="false"
label="#{msg['inv-manager.invDialog.descriptionFieldInputLabel']}"
immediate="true"
value="#{investigationManagerBackingBean.selection.description}" />
<p:commandButton id="okButton"
value="#{msg['inv-manager.invDialog.okButton']}" type="submit"
partialSubmit="true" process="investigationEditorForm"
action="#{investigationManagerBackingBean.createOrUpdate()}"
onclick="dlg.hide();" />
</h:panelGrid>
</h:form>
</p:panel>
</p:dialog>
The backing bean is configured to be #ViewScoped and everything works as defined. However, upon update the values of the p:datascroller are reset and the load method of the lazy loading model is executed and the datascroller is repopulated with new values from the database.
I have no reference to the datascroller or its containing form in the p:dialog and am wondering why the datascroller is being updated automagically? What am I missing in the equation. Have I overlooked something or something specific to the p:datascroller model that I need to consider when following this approach?
Look forward to the expertise of the community in resolving this issue.
Many thanks in advance :)

Unable to validate for primefaces event blur?

I am not able to validate input fields using primefaces ajax on the client side by calling event blur using primefaces
<h:panelGrid columns="2">
<p:outputLabel for="uname" value="Name"/>
<p:inputText id="uname" value="#{userbean.name}" required="true" requiredMessage="Enter your name">
<p:ajax event="blur" rendererType="name"/>
</p:inputText>
<h:outputText value=""/>
<p:message id="name" for="uname" />
<p:outputLabel for="add" value="Address"/>
<p:inputText id="add" value="#{userbean.address}" required="true" requiredMessage="Enter your address">
<p:ajax event="blur" rendered="address"/>
</p:inputText>
<h:outputText value=""/>
<p:message id="address" for="add" />
<h:commandButton value="Submit"/>
</h:panelGrid>
I am not sure what you're doing with 'rendererType and rendered' on your ajax events - they make no sense and ikely just breaking.
I've got it working fine in the below example (note my bean is different name) - i made the grid only 1 in colum size just for testing purposes and you're best off wrapping those full data objects you want re-rendered after ajax request. see the below code p:ajax uses 'update' to render content, where f:ajax uses render="id" etc..
<h:form>
<h:panelGrid columns="1">
<h:panelGroup layout="block" id="nameSection" >
<p:outputLabel for="uname" value="Name"/>
<p:inputText id="uname" value="#{onBlur.name}" required="true" requiredMessage="Enter your name">
<p:ajax event="blur" update="nameSection"/>
</p:inputText>
<h:outputText value=""/>
<p:message id="name" for="uname" />
</h:panelGroup>
<h:panelGroup layout="block" id="addressSection" >
<p:outputLabel for="add" value="Address"/>
<p:inputText id="add" value="#{onBlur.address}" required="true" requiredMessage="Enter your address">
<p:ajax event="blur" update="addressSection"/>
</p:inputText>
<h:outputText value=""/>
<p:message id="address" for="add" />
</h:panelGroup>
</h:panelGrid>
<h:commandButton value="Submit"/>
</h:form>

View display wrong behavior when there's a required="true" within the body

I have a view which is working well. However, when I add a required="true" into the body of the view, the view begin to be unable to read backing bean properly. Below is a comparison:
Anyone knows why?
.
Edit: Code fragment supplement
Below is the fragment of my code in which the problem arises. If I add required="true" into any p:inputText (not only the p:inputText that belong to this dialog but any p:inputText inside the html body), it stops displaying information from backing bean, remove it and everything works just fine.
<p:dialog header="Customer Editor" widgetVar="customerEditDialog"
resizable="false" id="customerEditDlg" showEffect="fade"
hideEffect="fade" modal="true">
<h:panelGrid id="editGrid" columns="2" cellpadding="4"
style="margin:0 auto;">
<h:outputLabel for="customerNameEdit" value="Name: " />
<p:inputText id="customerNameEdit" maxlength="30"
value="#{customerController.customerAdd.name}" />
<h:outputLabel for="customerPhoneNumberEdit" value="Phone Number " />
<p:inputText id="customerPhoneNumberEdit" maxlength="15"
onkeypress="if(event.which < 48 || event.which > 57) return false;"
value="#{customerController.customerAdd.phoneNumber}" />
<h:outputLabel for="customerEmailEdit" value="Email: " />
<p:inputText id="customerEmailEdit" maxlength="49"
value="#{customerController.customerAdd.email}" />
<h:outputLabel for="customerAddressEdit" value="Address: " />
<p:inputText id="customerAddressEdit" maxlength="190"
value="#{customerController.customerAdd.address}" />
<f:facet name="footer">
<div style="text-align: right">
<p:commandButton id="editCustomerButton"
update=":form:customerList, :form:messages"
oncomplete="customerEditDialog.hide()" value="Save"
actionListener="#{customerController.editCustomer()}">
</p:commandButton>
<p:commandButton id="cancelEditCustomerButton" update=":form"
onclick="customerEditDialog.hide()" value="Cancel">
</p:commandButton>
</div>
</f:facet>
</h:panelGrid>
</p:dialog>
See if jsf required=true destroys setPropertyActionListener? helps you.
The problem is most likely that the setter in your bean is not to be called because of validation errors somewhere else or you are nesting <h:form> elements.

Insert only digits as input

Currently I have a <h:inputText>
<h:outputLabel value="#{locale.nroEmployees}:"/>
<h:inputText value="#{companyEditBean.companyEmployeesAmount}"
disabled="#{not companyEditBean.editingAllowed}">
</h:inputText>
How can I achieve, that the user can only type digits in input fields?
You can filter it afterwards to only accept numbers, or do somehting similar to:
<h:inputText value="#{companyEditBean.companyEmployeesAmount}"
disabled="#{not companyEditBean.editingAllowed}"
onkeypress="if(event.which < 48 || event.which > 57) return false;"/>
As an alternative way, you can use primeface for achieving this:
<h:form>
<h:panelGrid columns="2">
<h:outputText value="Number Input"/>
<h:inputText id="txt_" />
</h:panelGrid>
<p:keyFilter for="txt_" mask="num" />
</h:form>
Or, with primeface extension you can do this (assuming you added required jar and defining extension namespace as pe)
<p:inputText id="txt_" required="false" label=""
value="#{beanclass.blablamethod}" maxlength="10">
<f:validateLength minimum="10" for="txt_" />
<pe:keyFilter regEx="/[\d\-]/"></pe:keyFilter>
</p:inputText>

How to submit values in a pop-up panel?

I have bean struggling to understand how to use the rich:popupPanel component in the right way. There are (at least not that I could find) few post about how to use the rich:popupPanel and how to submit values from it.
To make matter worse the panel seams to add (when checking the html) a hard coded "_content" to its component id name (to the div generated). I have tried to use aj4:region tag to partial render the complete form. But that didn't seamed to work, cause nothing where posted to managed bean. So now I have one option left, where the panel has its own form, outside the main one on the page.
I can see that the evaluation of the form (popup) values is happening, but not the execution of the bean function that persist the values (I see the POST request of the command button). The only reason I can think of at the moment, is that the pop-up panel use another bean to persist the values that the main form on the page (both of them are session scoped).
I am thinking of omit the pop-up panel all together, since it seams so hard to make this work. Maybe its a well know secret, since it so few post about it. It behaves the same if if use componentController or only a a4j:commanLink.
How is it possible to submit values from a rich:popupPanel and invoke a backing bean function to persist the pop-up form values ?
Appreciate if someone can shed some light on this, greetings Chris.
I use Richfaces 4.0-final on Glassfish 3.1
<h:form id="main_form">
<!-- Command for popup -->
<a4j:commandLink actionListener="#{userController.prepareCreateSysRequest}" oncomplete="#{rich:component('popup_sys_user_req_form:popup_sys_user_req')}.show(); return false;"
execute="#this" value="Request New Sector/Category" />
...
<a4j:commandButton action="#{projectController.Create}" ...>
</h:form>
<h:form id="popup_sys_user_req_form">
<rich:popupPanel id="popup_sys_user_req" modal="true" autosized="true" resizeable="false">
<f:facet name="header">
<h:outputText value="New Project Request" />
</f:facet>
<f:facet name="controls">
<h:outputLink value="#"
onclick="#{rich:component('popup_sys_user_req')}.hide(); return false;">
X
</h:outputLink>
</f:facet>
<h:panelGrid columns="2">
<h:outputLabel value="Request New:" />
<h:selectOneMenu id="sys_req_type" value="#{userController.selectedSysRequestType}" required="true" requiredMessage="Request Type is required" title="Request Type">
<f:selectItems value="#{userController.getSysRequestTypeItems()}">
</f:selectItems>
</h:selectOneMenu>
<h:outputLabel value="Description:" />
<h:inputTextarea id="user_req_desc" value="#{userController.selectedSysUserRequest.description}" required="true" requiredMessage="Decription is missing" />
</h:panelGrid>
<a4j:commandButton action="#{userController.CreateSysUserRequest}" onclick="#{rich:component('popup_sys_user_req')}.hide(); return false;" execute="#form" render="popup_sys_user_req_form" value="Send Request" />
</rich:popupPanel>
</h:form>
For what I have done I used to have the issue to got to submit twice only the first time.
To fix it the form got to be outside the popupPane. And also that the popupPanel should have the attibute domElementAttachment="form".
Example.
<h:form>
<rich:popupPanel id="shipmentItemUpdateDialog"
autosized="true"
domElementAttachment="form">
<f:facet name="header">
<h:panelGroup>
<h:outputText value="#{shipmentBundle.shipmentItemDetailsHeader}" />
</h:panelGroup>
</f:facet>
<f:facet name="controls">
<h:commandLink>
<h:graphicImage value="/core/images/modal/close.png"/>
<rich:componentControl target="shipmentItemUpdateDialog" operation="hide" />
</h:commandLink>
</f:facet>
<h:outputText for="shipmentItemName"
value="#{coreBundle.requiredChar} #{shipmentBundle.shipmentItemName}"
/>
<h:inputText id="shipmentItemName"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.name}"
label="#{shipmentBundle.shipmentItemName}"
size="40" >
</h:inputText>
<h:outputText for="shipmentItemCode"
value="#{coreBundle.requiredChar} #{shipmentBundle.shipmentItemCode}"
/>
<h:inputText id="shipmentItemCode"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.code}"
label="#{shipmentBundle.shipmentItemCode}"
size="40" >
</h:inputText>
<h:outputText value="#{coreBundle.requiredChar} #{shipmentBundle.shipmentItemAmount}"
/>
<h:inputText id="shipmentItemAmount"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.amount}"
label="#{shipmentBundle.shipmentItemAmount}"
size="4" >
<f:validateLongRange minimum="1"/>
</h:inputText>
<h:outputText value="#{coreBundle.requiredChar} #{shipmentBundle.shipmentItemNeedsCooling}"
/>
<h:selectBooleanCheckbox id="shipmentItemNeedsCooling"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.needsCooling}"
label="#{shipmentBundle.shipmentItemNeedsCooling}"
/>
<h:outputText for="shipmentItemDetails"
value="#{shipmentBundle.shipmentItemDetails}"
/>
<h:inputTextarea id="shipmentItemDetails"
disabled ="false"
required ="true"
value="#{shipmentItemController.shipmentItemUI.value.details}"
label="#{shipmentBundle.shipmentItemDetails}"
cols="38"
rows="5"
/>
</h:panelGrid>
<h:panelGrid columns="1" dir="LTR">
<h:panelGrid columns="2" dir="LTR">
<a4j:commandButton value="#{coreBundle.acceptButton}"
action="#{shipmentItemController.onUpdate()}"
render="shipmentItemsTable">
</a4j:commandButton>
<h:commandLink value="#{coreBundle.closeLink}"
immediate="true">
<rich:componentControl target="shipmentItemUpdateDialog" operation="hide" />
</h:commandLink>
</h:panelGrid>
<h:outputText value="#{coreBundle.requiredText}"/>
</h:panelGrid>
</rich:popupPanel>
</h:form>
I hope this helps.
I think you got it right.. think of the pop-up as a regular page. To submit and close the pop-up, do something like this:
<a4j:commandButton value="Save" onclick="#{rich:component('panelId}.hide();" render="..."/>
Hope this helps..

Resources