JSF update component from different form, boths forms with prependid false - jsf

Hi i have this sceneario, i have 2 forms each of them with preprendId=false, the first one have a h:panelGroup that i want to update from the second h:form. The problem that i have
is that i dont know what String i have to put for update my panelGroup. I tried with this strings:
panelGroupComboId and :panelGroupComboId
But i always get: Cannot find component with expression ":panelGroupComboId" referenced from...
Because i need to use preprendId=false at least in the first form (where my panelGroup is) i cannot set preprendIf=true, but if i did it i could update my component with any problem using: :loginFormRegistroId:panelGroupComboId
But remember i NEED to use preprendId= false, when i use preprendId=false i can see using
firebug that my h:panelGroup is converted as a div with the id panelGroupComboId, then thats why i dont how do i have to call for update it.
Is preprendId=true the only way to this works?
FIRST FORM
<h:form id="loginFormRegistroId" prependId="false">
<h:panelGroup id="panelGroupComboId" layout="block">
<select id="comboCarreraId" name="comboCarreraId" class="form-control">
<ui:repeat value="#{miBean.list}" var="obj">
<option value="#{obj.id}">#{obj.name}</option>
</ui:repeat>
</select>
</h:panelGroup>
</h:form>
SECOND FORM
<h:form prependId="false">
<p:remoteCommand
name="cargarCarrerasRemoteCommand"
process="#this"
actionListener="#{miBean.myListener}"
update="panelGroupComboId">
</p:remoteCommand>
</h:form>
By the way i DONT want to update the entire first FORM, just my h:panelGroup

Remove prependId from the forms. Update the code as
<h:form>
<p:remoteCommand
name="cargarCarrerasRemoteCommand"
process="#this"
actionListener="#{miBean.myListener}"
update=":loginFormRegistroId:panelGroupComboId">
</p:remoteCommand>
</h:form>

Related

Primefaces form is not updating from within dialog

I have a view like so:
<h:form id="productForm">
<p:messages
id="productFormMessages"
autoUpdate="true"
redisplay="true"
globalOnly="true" />
<p:panelGrid
id="detailsGrid">
<p:row>
...
<p:column>
...
<p:outputLabel
id="fieldToUpdateId"
value="XYZ" />
<p:commandButton
action="#{bean.prepareDialog}"
update="dialogFormId"
oncomplete="PF('dialogModal').show();" />
</p:column>
</p:row>
</p:panelGrid>
</h:form>
<ui:include src="/../.../dialog.xhtml" />
And this is what dialog.xhtml looks like:
<p:dialog
id="dialogId"
widgetvar="dialogModal"
appendTo="#(body)"
modal="true"
dynamic="true">
<h:form
id="dialogFormId">
...a selectOneMenu...
<p:commandButton
id="saveButtonId"
value="Save"
actionListener="#{bean.save}"
oncomplete="PF('dialogModal').hide();"
process="#form"
update=":productForm" />
</h:form>
But the save button just refuses to update the productForm. It does update productFormMessages (which I'm guessing is because of the autoUpdate) but the form just doesn't update. I need to do a page reload from the browser in order for it to reflect the latest data. I have tried many different ways of doing this.
1. Using p:component to directly refer to the outputLabel in the update attribute.
2. (1) also using the form ID and the panelGrid ID.
3. Using the full client ID (with and without the preceeding ':') in the update attribute. Similarly using the form ID and the panelGrid ID.
4. Adding the client ID to the render IDs in the bean and then calling the partialViewContext#update method on that.
4. Setting partialViewContext#setRenderAll to true.
4. And as a last ditch attempt, as demonstrated by the code, updating the entire productForm. Which isn't so bad, because fieldToUpdateId is just one of the fields that I need to update in the form. But either way, it's not working.
Clearly, the data is being saved on the back end, because a page reload gives me the latest data. But I just can't get the dialog to update the form where it's being called from. I'm out of ideas. What am I doing wrong?
Theoretically this should work, But please inspect the button in the Html source, to make sure which part of the html it refresh. it should have something like this.
onclick="PrimeFaces.ab({s:'dialogFormId:saveButtonId1',u:'productForm',onco:function(xhr,status,args){PF('dialogModal').hide();;}});return false;"

<p:overlayPanel> shows blank white after updating via command link/button

I am looking for solution that p:overlayPanel content should update it self while clicking commendButton or commendLink. But its showing blank white p:overlayPanel when i click the button. The updating with the p:overlayPanel id in that button or link. I have tried many ways nothing worked out. Is my code wrong?
Please suggest some solution.
Here is my code :
<ui:repeat id="profiles" value="#{items.lstProfiles}" var="profile">
<p:commandLink id="profileLink" value="show" update="moviePanel"
actionListener="#{dashBoardController.showProfileOverlay}"/>
<p:overlayPanel id="moviePanel" for="profileLink" hideEffect="fade"
dynamic="true" style="width:300px; height: 150px;">
<h:panelGrid columns="2">
<h:outputText value="Name : "/>
<h:outputText value="#{dashBoardController.selectedProfile.name}"/>
</h:panelGrid>
</p:overlayPanel>
</ui:repeat>
Usually dynamic="true" should do the job but some times it fails.So to update the contents inside the Overlay.
There are many ways to do this by tweaking Jquery.
Simplest one I can think of is:
Since ui:repeat generates dynamic ID for p:overlayPanels you can update by providing unique css class name from every iteration.
In Primefaces you can select a component using css class also using: #(.myclass).
And so you can update that component also:- update="#(.mystyle)"
Example:
<h:form>
<ui:repeat var="patient" value="#{dataCenter.patientList}">
<p:commandLink value="#{patient.firstName}" id="patientNameLnk" update="#(.overlay-class-#{patient.patientId})"/><br/>
<p:overlayPanel for="patientNameLnk">
<h:panelGroup styleClass="overlay-class-#{patient.patientId}">
#{patient.firstName}
#{patient.lastName}
#{patient.dob}
</h:panelGroup>
</p:overlayPanel>
</ui:repeat>
</h:form>
In the above example css class name for every h:panelGroup will be generated as overlay-class-<PATIENT_ID> so every h:panelGroup will have unique class name(if patientId is unique).
Note: Note that I'm updating h:panelGroup inside p:overlayPanel because if you update p:overlayPanel then it might start flickering(it happened to me while executing above example).

Myfaces, facesContext.messageList always empty unless it's parent has a rendered="#{not empty facesContext.messageList}"

I want to create a simple register form with JSF2 ajax and Bean Validation, which allows to display all error messages with custom format in the ui:repeat value="#{facesContext.messageList}" var="m" area when the validation fails. My code works well with Mojarra, but when I switch to Myfaces2.1, the messages never show with ui:repeat -- it only leaves an empty oltag there, and the facesContext.messageList seems to be empty. It still works with h:messages but that's not what I want.
However, today I found a wierd workaround: Adding the attribute rendered="#{not empty facesContext.messageList}" to one of the ui:repeat's parent component.
I can't understand why this rendered="..." matters because the errorDisplay component did get re-rendered everytime. Does this test #{not empty facesContext.messageList} change anything ?
<h:form>
Name:<h:inputText value="#{hello.name}" id="name"/>
<br/>
Age :<h:inputText value="#{hello.age}" id="age" converterMessage="'Age'必须是一个数字"/>
<h:commandLink value="register" type="submit">
<f:ajax execute="#form" render="errorDisplay"/>
</h:commandLink>
<h:panelGroup> <!--rendered="#{not empty facesContext.messageList}"-->
<h:panelGroup id="errorDisplay"><!--rendered="#{not empty facesContext.messageList}"-->
<span>发生以下错误:</span>
<ol style="color:red;">
<ui:repeat value="#{facesContext.messageList}" var="m">
<li>${m.detail}</li>
</ui:repeat>
</ol>
</h:panelGroup>
</h:panelGroup>
</h:form>

Using jQuery Mobile popup with JSF

Consider the following JSF (& jQuery Mobile) markup:
<h:form>
Please login
<h:outputText id="greeting" value="Welcome, you have logged in" rendered="#{sessionScope.login == null ? false : true}"/>
<div id="login" data-role="popup">
<h:inputText value="#{requestScope.userName}"/>
<h:inputHidden value="#{requestScope.password}"/>
<h:commandButton value="login" action="#{loginBacking.processLogin}">
<f:ajax execute="#form" render="greeting"/>
</h:commandButton>
</div>
</h:form>
Obviously the above markup will not send the user input to the server, because jQuery Mobile popup needs <h:form/> tag inside popup. But if I put the <h:form/> tag inside popup, I cannot use <f:ajax render="greeting"/> (because the id "greeting" left outside).
How can I overcome this issue without using boilerplate Javascript codes?
You can just use absolute client IDs in <f:ajax render>. If you start with the JSF NamingContainer separator character, which defaults to :, then it will be resolved relative to the UIViewRoot. So you can just use render=":greeting".
You've by the way another problem. You cannot update components in JS/Ajax/client side which are by itself not rendered in JSF/server side, simply because there's then nothing in the HTML DOM tree which can be referenced and updated. You need to wrap the <h:outputText id="greeting"> in another component which is always rendered.
So, all with all, this should do for you:
Please login
<h:panelGroup id="greeting">
<h:outputText value="Welcome, you have logged in" rendered="#{login != null}"/>
</h:panelGroup>
<div id="login" data-role="popup">
<h:form>
<h:inputText value="#{requestScope.userName}"/>
<h:inputHidden value="#{requestScope.password}"/>
<h:commandButton value="login" action="#{loginBacking.processLogin}">
<f:ajax execute="#form" render=":greeting"/>
</h:commandButton>
</h:form>
</div>
(note that I have simplified the EL expression in the rendered attribute, it makes no sense to use a conditional operator to return boolean results while the expression by itself already returns a boolean result; I'd myself have preferred rendered="#{not empty login}" by the way)
See also:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?

How to update a component inside of dataTable from outside of it

I am using Mojarra implementation of JSF 2.1 with Primefaces 3.2.
My problem approximately looks like this:
<p:dialog id="someDialog">
..
<h:form id="dialogForm">
<p:commandLink action=".."update=":someForm:someUIRepeat:someDataTable:someInputTextArea"/>
</h:form>
</p:dialog>
<h:form id="someForm">
<ui:repeat id="someUIRepeat" value=".." ..>
<p:dataTable id="someDataTable" value=.. >
<p:column>
<p:inputTextarea id="someInputTextarea" value=../>
<p:column>
.. here go other columns
<ui:repeat>
</h:form>
The issue is that when I click on the commandLink in the dialog the inputTextarea is not updated. However, if I write this in the update of the commandLink:
update=":someForm:someUIRepeat:someDataTable,:someForm:someUIRepeat:someDataTable:someInputTextArea"
then the whole dataTable gets updated and the inputTextarea updates as well, but the values in the fields located in other columns get erased after I click on the commandLink in the dialog.
The reason why I put dataTable inside of ui:repeat is that I need to bind a dataTable with each row of one collection and I think it's not related to my problem.
Any ideas how I can solve this problem?
Thanks in advance,
Nurzhan.
for start try this
added onclick="jQuery('#someForm:someButton').click();"(check the exact id of your hidden button) to your <p:commandLink inside the dialog
set the update to update=":someForm:someUIRepeat:someDataTable"
and add
<h:commandButton id="someButton" style="display:none">
<f:ajax execute="#form"></f:ajax>
</h:commandButton>
to <h:form id="someForm">
explanation: the purpose of the hidden button is to execute (send its values) the form to the server so that when you do call update the fields wont be erased...

Resources