Bean property not updated on action - jsf

I have the following Facelet page:
<ui:define name="content">
<h:form id="selectReport">
<div>
<h:selectOneMenu value="#{reportsController.selectedReport}">
<f:selectItems value="#{reportsController.reportsList}"/>
</h:selectOneMenu>
</div>
<div>
<h:commandButton value="Ir al reporte"
action="#{reportsController.goToReport}"/>
</div>
</h:form>
<h:form id="dateRangeSetupForm"
rendered="#{reportsController.showDateRangeSetupForm}">
<div>
<h:outputLabel value="Desde:"/>
<h:inputText id="fromDate"
value="#{reportsController.fromDate}"/>
</div>
<div>
<h:outputLabel value="Hasta:"/>
<h:inputText id="toDate"
value="#{reportsController.toDate}"/>
</div>
</h:form>
<h:form id="billOfLadingSetupForm"
rendered="#{reportsController.showBillOfLadingSetupForm}">
<div>
<h:outputLabel value="# Factura:"/>
<h:inputText id="invoiceNumber"
value="#{reportsController.invoiceNumber}"/>
</div>
</h:form>
<h:form id="submitForm">
<h:commandButton id="processReport" value="Generar Reporte"
action="#{reportsController.processReport}"/>
<h:commandButton id="goBack" value="Regresar"
action="mainMenu"/>
</h:form>
</ui:define>
In which I let the user select a report, and render a form to setup parameters depending on the report. The problem is that when I render for example the billOfLadingSetupForm and fill the inputText, then click on the processReport button the invoiceNumber property of my bean is not updated, it is set to null.
I have noticed that if I type Return after filling the inputText and then click the processReport button the property does get updated. This is strange I haven't face this problem before. Do you have any idea why this happens?

Whenever a form get submitted, then only the data inside that form will be sent. The data of the other forms won't be sent. That's by HTML specification. You need to put all inputs and buttons which belongs to each other inside the same <h:form>. Replace all your splitted dateRangeSetupForm, billOfLadingSetupForm and submitForm forms by <h:panelGroup> and put them all inside one and same <h:form>.
Something like this:
<ui:define name="content">
<h:form>
<div>
<h:selectOneMenu value="#{reportsController.selectedReport}">
<f:selectItems value="#{reportsController.reportsList}"/>
</h:selectOneMenu>
</div>
<div>
<h:commandButton value="Ir al reporte" action="#{reportsController.goToReport}"/>
</div>
</h:form>
<h:form>
<h:panelGroup id="dateRangeSetupForm" rendered="#{reportsController.showDateRangeSetupForm}">
<div>
<h:outputLabel value="Desde:"/>
<h:inputText id="fromDate" value="#{reportsController.fromDate}"/>
</div>
<div>
<h:outputLabel value="Hasta:"/>
<h:inputText id="toDate" value="#{reportsController.toDate}"/>
</div>
</h:panelGroup>
<h:panelGroup id="billOfLadingSetupForm" rendered="#{reportsController.showBillOfLadingSetupForm}">
<div>
<h:outputLabel value="# Factura:"/>
<h:inputText id="invoiceNumber" value="#{reportsController.invoiceNumber}"/>
</div>
</h:panelGroup>
<h:commandButton id="processReport" value="Generar Reporte" action="#{reportsController.processReport}"/>
<h:commandButton id="goBack" value="Regresar" action="mainMenu"/>
</h:form>
</ui:define>
Make sure that the bean is put in the view scope. Otherwise the conditions for the rendered attribute won't be preserved. See also commandButton/commandLink/ajax action/listener method not invoked or input value not updated

Related

globalOnly="true" in h:messages and bean validation

I use globalOnly="true" in h:messages to show messages as success or errors during bean methods......
<div class="row">
<div class="col">
<h:messages id="mensagens" warnClass="alert alert-danger" infoClass="alert alert-success" errorClass="alert alert-danger" globalOnly="true" />
</div>
</div>
and h:message for="" to validate field by field with bean validation
<h:inputText id="nome" styleClass="form-control" value="#{lojaMB.filial.nome}" />
<h:message for="nome" class="text-danger" />
It's works well......
But when I click on the "+" green button the modal opens
This modal use other managed bean and other form with ajax...
<h:commandButton value="Salvar" styleClass="btn btn-secondary" action="#{supermercadoMB.salvar}">
<f:ajax execute="#form" render=":mensagens :frmNovaFilial:supermercado #form" onevent="hideModal" />
</h:commandButton>
THE PROBLEM
when I click "Salvar" button the function "hideModal" executes, modal closes and bean validation send a error message by the blank field to parent page h:messages (no h:message ...) ....... but this message doesn't show........ Just shows when I remove globalOnly="true" .....but If I remove globalOnly="true" validations of field by field are show too on h:messages and h:message ......
how resolve this?
Create a parent element to your message component and after process the button update it
In the commandButton process only the nome inputText and the button itself
<h:panelGrid id="grid" columns="1">
<h:inputText id="nome" styleClass="form-control" value="#{lojaMB.filial.nome}" />
<h:message for="nome" class="text-danger" />
</h:panelGrid>
<h:commandButton value="Salvar" action="#{supermercadoMB.salvar}">
<f:ajax execute="#this :nome" render=":grid" onevent="hideModal" />
</h:commandButton>

Passing/binding inputfield UIInput.value inside ui:repeat to bean method

I've comments that are displayed from an <ui:repeat> tag. An user can reply to to all comments with input fields that are displayed individually for each comment. However I can't manage to pass the value of the comment to the bean that deals with it. I thought about passing the UIInput value as described in the first answer [by balusC here][1]. The problem is that the content is empty because the action button is bound to every UIInput ( I believe so). I should sort of have a personal bound between each button and my UIInput. I think the code is gonna be more self-explanatory hopefully. :
<ui:repeat var="post" value="#{watchThread.listeFirstPosts}">
<h:outputText value="#{post.user.username}"/>
<div class="postContent">
<h:outputText value="#{watchThread.sanitize(post.content)}" />
</div>
<div class="replyAction">
<h:form>
<div class="inputAreaPostFast">
<p:inputTextarea id="reply2" value="#{watchThread.replyContent}" binding="#{inputReply}"/>
<div class="replyBtn">
---------- Here the third param is the issue --------------
<p:commandButton action="#{watchThread.sendReply(userNav.user, post, inputReply.value)}"/>
</div>
</div>
</h:form>
</div>
</ui:repeat>
Edit: This is the code that worked for me. (I think) I had a form that had no business of being in my ui:repeat tag. Also to bind the input see the answer/comment of balusC below. However I had to let the form tags inside and not outside as suggested.
<ui:repeat var="post" value="#{watchThread.listeFirstPosts}">
<div class="replyBlock">
<h:panelGroup id="username" style="cursor:pointer;">
<div class="profileimgForum">
<h:graphicImage styleClass="profilepicForum" value="/images/#{post.user.profilePic}" rendered="#{!empty post.user.profilePic}"></h:graphicImage>
<h:graphicImage styleClass="profilepicForum" library="images" name="profilepic1.jpg" rendered="#{empty post.user.profilePic}"></h:graphicImage>
</div>
<span class="posterTitle">
<h:outputText value="#{post.user.username}"></h:outputText> </span>
<h:outputText value=" #{watchThread.formatTimeReply(post.datePost)}"/>
</h:panelGroup>
<div class="replyContent">
<h:outputText value="#{watchThread.sanitize(post.content)}" style="pointer:cursor;"/>
</div>
<div class="replyAction">
<p:inplace id="facet" effect="none">
<f:facet name="output">
#{strings.Reply}
</f:facet>
<f:facet name="input">
<h:form>
<div class="inputAreaPostFast">
<p:inputTextarea id="reply2" cols="70" rows="7" value="#{watchThread.replyContent}" binding="#{inputReply}" maxlength="500"/>
<div class="replyBtn">
<p:commandButton update="growl" style=" margin-right: 2em;" value="#{strings.Reply}" action="#{watchThread.sendReply(userNav.user, post, inputReply)}"/>
</div>
</div>
</h:form>
</f:facet>
</p:inplace>
</div>
<ui:repeat var="areply" value="#{post.posts}">
#{areply.content} ----
</ui:repeat>
</div>
<!-- ####### Dialog username ######## -->
<p:overlayPanel for="username" id="usernamePanel" dynamic="true" showCloseIcon="true" appendToBody="1" dismissable="false">
<div class="dlgTopBlock">
<div class="dlgPicBlock">
<h:graphicImage styleClass="profilePicDialog" value="/images/#{post.user.profilePic}" rendered="#{!empty post.user.profilePic}"/>
<h:graphicImage styleClass="profilePicDialog" library="images" name="profilepic1.jpg" rendered="#{empty post.user.profilePic}"/>
</div>
<div class="dlgTopSubBlock"><div class="dlgTopTitle">
<h:graphicImage styleClass="flag" library="images/flags"
name="#{post.user.countryBean.iso2}.png"
rendered="#{! empty post.user.countryBean.iso2}"/>
<h:link value="#{post.user.username}" outcome="/user.xhtml">
<f:param name="username" value="#{post.user.username}"></f:param>
</h:link>
</div>
<div class="dlgRep">
<h:outputText value="#{post.user.reputation} #{strings.repPoints} "></h:outputText>
</div>
<div class="dlgTopStatus">
<h:outputText value="#{post.user.status}"/></div>
</div>
</div>
<div class="btnDlg">
<h:panelGroup rendered="#{userNav.isUserConnected and userNav.username != post.user.username}">
<p:commandButton value="#{usernavmsg.SendPM}" icon="ui-icon-mail-closed" onclick="PF('sendMsgDlg').show();"></p:commandButton>
<p:commandButton id="addFriend" value="#{friendBean.btnText}" action="#{friendBean.addFriend()}" update="growl addFriend" icon="#{friendBean.icon}"
rendered="#{friendBean.rendered}"/>
</h:panelGroup>
</div>
<p:dialog header="#{usernavmsg.SendingTo}: #{post.user.username}"
dynamic="true" modal="false" widgetVar="sendMsgDlg" minHeight="40">
<h:form>
<p:inputTextarea value="#{pMbean.title}" rows="1" cols="110" id="title" >
<f:passThroughAttribute name="placeholder" value="#{usernavmsg.Title}"/>
</p:inputTextarea><br/><br/>
<p:inputTextarea value="#{pMbean.message}" id="msg" rows="10" cols="110" autoResize="true">
<f:passThroughAttribute name="placeholder" value="#{usernavmsg.YourMsg}"/>
</p:inputTextarea><br/>
<p:commandButton style="float:right;" value="#{usernavmsg.Send}" action="#{pMbean.send(post.user)}"
onclick="PF('sendMsgDlg').hide();" icon="ui-icon-mail-closed" update="growl"></p:commandButton>
</h:form>
</p:dialog>
</p:overlayPanel>
<!-- ######### End of dialog user ######## -->
</ui:repeat>
The only visible mistake is the below:
<ui:repeat value="#{watchThread.listeFirstPosts}" var="post" ...>
<p:inputTextarea ... value="#{watchThread.replyContent}">
You're basically binding the value of the input field of every iteration to one and same backing bean property. So, every iteration round will override the value of the previous iteration round. This is not right. The value of the input field must be bound to the current iteration round. I.e. it should basically have been as below:
<ui:repeat value="#{watchThread.listeFirstPosts}" var="post" ...>
<p:inputTextarea ... value="#{post.replyContent}">
But, in this construct you actually don't need it. Just get rid of the value attribute altogether and rely on binding as you initially wanted to use.
Then, there's another mistake as pointed out in the comments: nesting forms. This is illegal in HTML. Don't write JSF code in such way that it produces illegal HTML. There would be another potential cause in form of a bug in Mojarra which only exposes in case you're using <f:ajax> in a nested <ui:repeat>. The solution to that would be using a fullworthy UIData component, such as <h:dataTable> or one of PrimeFaces grids.

p:command to submit a form in overlaypanel

I am trying to put a p:commandButton inside a overlayPanel, to submit the information of a h:form and redirect to another view. So, I use the property action of the button to perform this operation. I have a managed bean associated with this view but the function used for this purpose is never reached. Can u help me?
Here is the code:
advancedSearch-form.xhtml
<h:form>
<h:panelGrid width="100%">
<h:column>
....
</h:column>
....
<p:commandButton value="Submit" action="#{searchForm.save}">
</p:commandButton>
</h:panelGrid>
In another xhtml:
<h:form>
<div>
...
<div class="menu-search">
<p:commandButton id="advancedSearch" icon="ui-icon-carat-1-s" styleClass="ui-search-button" type="button"/>
<p:overlayPanel id="advancedSearchPanel" styleClass="ui-advanced-search-overlay" for="advancedSearch" hideEffect="fade" my="right top" dynamic="true" dismissable="false">
<ui:include src="/search/advancedSearch-form.xhtml"/>
</p:overlayPanel>
</div>
...
</div>
After looking over the properties of overlay, I solved this question by removing the dynamic property of overlaypanel.

p:outputPanel does not render page sections

I have two p:ouputPanels which have the rendered attribute. They should be rendered when the value of the underlying getter/setter changes. However, the underlying values change in the right order. The first panel disappears, However the second panel does not show up. Even NOT in the HTML code!
My two panels:
<p:outputPanel id="PanelParent">
<h:form>
<p:outputPanel id="PanelForm" rendered="#{PageService.isVisibilityForm()}">
<h:commandButton value="Button"
action="#{PageService.persist}"
styleClass="btn btn-primary opal_btn submit_form_new" />
</h:form>
</p:outputPanel>
<p:outputPanel id="PanelMessage" rendered="#{PageService.isVisibilityMessage()}">
//Message
</p:outputPanel>
</p:outputPanel>
I appreciate your answer!!!
-UPDATE-
In the code, I reference to the persist method and in this method I change the getter and setter of the visibility for each section.
-UPDATE1-
OK here is in fact my code:
<p:outputPanel id="parentPanel">
<p:outputPanel id="PanelForm"
rendered="#{PageService.isVisibilityForm()}">
<div>
<div>
<h:form class="homepage_invitee_form" action="" method="POST">
<p:messages id="messages" showDetail="false" autoUpdate="true"
closable="true" />
<h:inputText required="true"
value="#{PageService.instance.name}"
name="name" placeholder="Last Name"
styleClass="lastname_new" id="lastname_new"
type="text placeholder" />
<h:commandButton value="Press"
action="#{PageService.persist()}"/>
<f:ajax render="" />
</h:commandButton>
</h:form>
</div>
</div>
</p:outputPanel>
<p:outputPanel id="PanelThank"
rendered="#{PageService.isVisibilityThank()}">
<div>
Message
</div>
</p:outputPanel>
</p:outputPanel>
I really do not see where it fails? ;(
It's like Xtreme Biker said <f:ajax> render attribute will render elements that are already present in the DOM. In your case, <p:outputPanel id="PanelThank"> render attribute was evaluating to false so it was not in the DOM. Therefore, <f:ajax> could not render it. You need to point to something that is always visible. Change
<f:ajax render="" />
to
<f:ajax render=":PanelThank" />
but more importantly change
<p:outputPanel id="PanelThank" rendered="#{PageService.isVisibilityThank()}">
<div>
Message
</div>
</p:outputPanel>
to
<p:outputPanel id="PanelThank">
<p:outputPanel rendered="#{PageService.isVisibilityThank()}">
<div>
Message
</div>
</p:outputPanel>
</p:outputPanel>
Consider refactoring your code also. For instance, action and method in <h:form> is not needed.
rendered attribute defines if JSF will render your component in the DOM tree. Your problem is you cannot update a component which is not in the tree because you simply don't have it:
<p:outputPanel id="PanelForm" rendered="#{PageService.isVisibilityForm()}">
//my Form
<p:outputPanel>
<!--Fails if not PageService.isVisibilityForm(), because you don't have the component itself in the tree! So can't find it-->
<p:ajax update="PanelForm"/>
Your best is to wrap your content in another container which is always rendered and update it instead of the other one:
<h:panelGroup id="updatablePanel">
<p:outputPanel rendered="#{PageService.isVisibilityForm()}">
//my Form
<p:outputPanel>
</h:panelGroup>
<p:ajax update="updatablePanel"/>

jsf 2.0 f:convertDateTime for util.Date with using custom date pattern from .properties

After changing locale in action mathod with return null as I apologize page should be reload but field with date doesn't change after first click on link for changing locale. I use MyFaces
I have a page where user can set locale and after changing locale I can't get desired format of date just after second time push on link for changing locale. I use bean for localization from this post
localiztion article
I cant understand why in
<h:outputText value="#{newsVar.date}">
<f:convertDateTime pattern="#{msg['date.pattern']}" />
</h:outputText>
!!!! Edited!!!
I have some problems with getting id of dataField whem I use facets in mainLayout.xhtml
<f:view locale="#{localeManager.language}">
<div id="wrapper">
<div class="header">
<ui:insert name="header">
<ui:include src="/pages/template/commonHeader.xhtml" />
</ui:insert>
</div>
<div class="content_container">
<ui:insert name="content" />
</div>
</div>
</f:view>
commonHeader is included commandLink
<ui:composition>
<h:form>
<h1>
<h:outputText value="#{msg['header.text']}" />
</h1>
<div class="lang_selector">
<h:commandLink action="#{localeManager.changeLanguage('ru')}"
value="#{msg['header.language.ru']}">
<!-- <f:ajax render=":listGroupId:dateField" />-->
</h:commandLink>
<h:commandLink action="#{localeManager.changeLanguage('en')}"
value="#{msg['header.language.en']}">
<!-- <f:ajax render=":listGroupId:dateField" />-->
</h:commandLink>
</div>
</h:form>
</ui:composition>
And in current page I have next
<ui:composition template="/pages/layouts/mainLayout.xhtml">
<ui:define name="content">
<f:event type="preRenderView" listener="#{news.showNews}" />
<h:form id="listForm" prependId="false">
<h:panelGroup id="listGroupId">
<ui:repeat var="newsVar" value="#{news.newsList}">
<div class="news_item">
<div class="news_title">
<h1>
<h:outputText value="#{newsVar.title}" />
</h1>
<div class="news_date">
<h:outputText id="dateField" value="#{newsVar.date}">
<f:convertDateTime pattern="#{msg['date.pattern']}" />
</h:outputText>
</div>
As you can see a try to get id of "dateField" but that id in different form. I read next article How to JSF 2.0: – render components outside of the form I understand that I should set <h:form id="listForm" prependId="false"> then I can set elementId in <f:ajax/> without name of form but I get error javax.faces.FacesException - Component with id::listGroupId:dateField not found.
And I find that: The element which is specified in render must be already present in the client side HTML DOM tree. May be that's why I have this problem
Please, help me...
Why is pattern for date changed only from 2nd time?
I would recommend the following
1) change setLanguage into changedLanguage (inside that method set the language attribute)
in general , its a bad practive to use setters in action attribute , and in general use get/set prefix in actionmethods
2) add f:ajax
<h:commandLink action="#{localeManager.changedLanguage('en')}" value="#msg['header.language.en']}">
<f:ajax render="dateField"/>
</h:commandLink>
3) change h:outputText into
<h:outputText id="dateField" value="#{newsVar.date}">
<f:convertDateTime pattern="#{msg['date.pattern']}" />
</h:outputText>

Resources