p:commandButton denying another p:commandButton - ajax

First off let me say I'm at most an intermediate JSF coder.
Now I have an odd problem with some primefaces buttons in my current project and it's really starting to get to me.
The environment is creating a football match.
I have 3 lists of players. The idea is that the user selects a player from the first list and then presses either the "Benched" button to add the player to the benched list or the "Starting" button to pick a player position and then add the player to the starting list.
(I would post a picture but I'm not allowed to :( )
Now my issue is that whenever I use the "Starting" button it renders the "Benched" button completely useless (I get no errors but the action method is not called). So I can add as many players to the bench to start with but as soon as i press the "Starting" button I can't bench more players. I can still use the "Starting" button though.
Here's my code:
<h:form id="matchForm">
<h:panelGroup id="updatePlayers">
<div class="myContainer">
<div class="myMatchBox">
<h:outputLabel value="Pick a player:" />
<p:selectOneListbox styleClass="heightClassPick myEditMatchPlayers myPickListOnEditMatches" filter="true" filterMatchMode="contains">
<f:selectItems value="#{manageMatchesBean.geteAllUsablePlayersOne()}" var="p" itemLabel="#{p.split('#')[0]} - #{p.split('#')[2]}" itemValue="#{p}"/>
<p:ajax event="valueChange" listener="#{manageMatchesBean.changeEPickedPlayerOne}" immediate="true"/>
</p:selectOneListbox>
<h:outputLabel style="display:block;" value="Add it to:" />
<p:commandButton styleClass="myMatchCommandButton" value="Starting" update="posdlg0table" oncomplete="PF('posdlg0').show();return false;"/>
<p:dialog header="Choose a position" widgetVar="posdlg0" modal="true" minHeight="40" resizable="false">
<h:dataTable id="posdlg0table" value="#{manageMatchesBean.getPickedPlayerPositionsOne()}" var="pos">
<h:column>
<p:commandButton value="#{pos.split('#')[0]}" update=":matchForm:updatePlayers" action="#{manageMatchesBean.eAddToStartingOne(pos.split('#')[1])}" process="#this" oncomplete="PF('posdlg0').hide();"/>
</h:column>
</h:dataTable>
</p:dialog>
<p:commandButton styleClass="myMatchCommandButton" value="Benched" update=":matchForm:updatePlayers" action="#{manageMatchesBean.eAddToBenchedOne()}" process="#this"/>
</div>
</div>
</h:panelGroup>
</h:form>
If I'm missing something or you want to see the java code let me know and I'll post it aswell.
I'm desperate!
Thanks in advance.
Alex

Apparently I solved it.. After several hours of trying to fix this I quit and wrote this question here and within 1 hour of writing it I found a tiny mistake in my java code. And yes apparently the method was called. Anyway. Now it works. Thanks.

Related

malformedXML: During update: outerTab:j_idt185 not found; iframe id="JSFFrameId"

I have a form with a PrimeFaces selectOneMenu which, when the user selects an option, I want to refresh a DataTable in the same form with different data. When I select an option I get a Javascript popup that says "malformedXML: During update: outerTab:j_idt185 not found" with no DataTable refresh and on inspecting the source I see an invisible iframe at the bottom of the page with id="JSFFrameId" that contains an element <partial-response> that in turn contains an element <update id="outerTab:j_idt185" ...> and this contains an element <![CDATA[<div id="outerTab:j_idt185" class="ui-messages ui-widget" aria-live="polite"></div>]]>. I think this references my <messages> tag, but nothing in the backing bean creates a message, and I do see an element in the page source <div id="outerTab:facilitatorTestsForm:j_idt113" class="ui-messages ui-widget" aria-live="polite"></div> where the messages should be, so the messages tag is indeed rendered. I can find no element with an ID containing "j_idt185" and apparently neither can some Javascript.
The "outerTab" in the IDs is a PrimeFaces TabView that contains all this stuff.
A page refresh causes the update to happen and the DataTable shows the correct data for the selected SelectOneMenu option.
I have found several posts by balusC where some element that is updated by an ajax call has a rendered value that makes it not render and therefore unable to be found when the update is called for. The target of my update (the DataTable) has no rendered attribute and is visible all the time, so this is a different problem. Other posts speak to a bug in earlier versions of PrimeFaces (I am using 6.1). I cannot figure out why this error occurs.
#Kukeltje kindly pointed me to several posts showing that using an encoding type of multipart/form-data in a file-upload component or a form submit can cause this problem but my page has neither of these.
Here is an excerpt of my page:
<div align="center">
<h:form id="facilitatorTestsForm">
<p:messages for="testBeanMessages" showSummary="true" showDetail="true" globalOnly="true" escape="false" autoUpdate="true" />
Tests for which event?
<p:selectOneMenu value="#{testBean.selectedEventId}" style="top: 7px; ">
<f:selectItem itemLabel="All Tests" itemValue="" />
<f:selectItems value="#{testBean.facilitatorEvents}" var="event" itemValue="#{event.id}" itemLabel="#{event.name}" />
<f:ajax update="facilitatorTests" />
</p:selectOneMenu>
<p:commandButton value="Add a New Test" style="margin: 20px;" oncomplete="PF('newTestDialog').show();" actionListener="#{testBean.createEmptyNewTest}" immediate="true" />
<p:dataTable var="test" value="#{testBean.testsForFacilitator}" rowIndexVar="index" id="facilitatorTests" widgetVar="facilitatorTests" selectionMode="single" selection="#{testBean.selectedTest}" rowKey="#{test.id}">
<p:ajax event="rowSelect" oncomplete="PF('facilitatorEditTestDialog').show(); " update="#form:facilitatorEditTestDialog" />
<p:column>#{index + 1}</p:column>
<p:column headerText="Test" sortBy="#{test.name}" width="40%"><h:outputText value="#{test.name}" /></p:column>
<p:column headerText="Tester" sortBy="#{test.tester.fullname}"><h:outputText value="#{test.tester.fullname}" /></p:column>
<p:column headerText="Manager" sortBy="#{test.manager.fullname}"><h:outputText value="#{test.manager.fullname}" /></p:column>
<p:column headerText="Event" sortBy="#{test.event.name}"><h:outputText value="#{test.event.name}" /></p:column>
<p:column headerText="Functional Area" sortBy="#{test.functionalArea.name}"><h:outputText value="#{test.functionalArea.name}" /></p:column>
<p:column headerText="Complete" width="150" sortBy="#{test.completionDate}"><h:outputText value="#{test.completionDate == null ? 'Not Completed' : test.completionDate}"><f:convertDateTime pattern="M/d/yyyy hh:mm a" /></h:outputText></p:column>
<p:column id="delete" style="text-align: center; vertical-align: middle; min-width: 54px; ">
<p:commandButton update="facilitatorTests" process="facilitatorTests" icon="ui-icon-close" actionListener="#{testBean.deleteTest(test.id)}"
title="If the test has not been completed, it will be deleted permanently. Otherwise it will be archived."/>
</p:column>
</p:dataTable>
<... a few dialogs with conditional rendering ...>
</h:form>
</div>
I have tried different targets for the selectOneMenu update attribute and it does not change the behavior so I believe it is correct.
Primefaces 6.1
Mojarra JSF API & IMPL 2.2.4
EL 3.0.0
Tomcat 7
Is this a JSF bug? Thanks for any help you can offer.
Found the solution. Thanks to #Kukeltje for staying with me through this even if he did downvote my question for not having enough info :)
It comes back to #BalusC's posts about not rendering the target of an ajax update. In this case I had several PrimeFaces TabView tabs containing <p:messages> tags with autoUpdate="true", and the tabs are shown/hidden depending on the role of the user. When I removed autoUpdate="true" from these messages tags the problem went away. Apparently every time I did an ajax post, even if I had partial submit limited to rendered subelements of the current visible tab, autoUpdate causes JSF to try to update the messages tags in the unrendered tabs and of course they cannot be found.
The way I found this was to put id attributes EVERYWHERE, on every element in my forms. Then the Javascript error pointed me to a named (id'd) element, rather than one with an automatically assigned ID that I could not trace, and when I saw "autoUpdate" the light bulb came on. Moral: put ids on EVERYTHING.
I hope this helps someone with the same symptom to look for autoUpdate everywhere.
And #Kukeltje you were right that my post had inadequate information - without the enclosing tab tags with their rendered attributes you could not have seen the problem. Since they were in another template that ui:includes the forms I did not think they were relevant. Wrongo!

How to dynamically show/hide components under p:tab via ajax?

Forgive me I am not even sure my question is correctly stated. I am trying to unravel relationship between p:tab and h:panelGroup. I have very shallow understanding of JSF. I have following code.
<p:tabView id="view">
<p:tab id="A">
...
<p:ajax event="change" update="C,D" listener="#{bean.captureValue}"/>
</p:tab>
<p:tab id="B" titleStyleClass="x">
<h:panelGroup id="C">
<h:panelGroup rendered="#{bean.checkValue eq 'Yes'}"/>
<f:facet name="title"><table>...</table></f:facet>
<div>....</div>
</h:panelGroup>
</h:panelGroup>
<h:panelGroup id="D">
<h:panelGroup rendered="#{bean.checkValue eq 'No'}"/>
<f:facet name="title"><table>.....</table></f:facet>
<div>....</div>
</h:panelGroup>
</h:panelGroup>
</p:tab>
</p:tabView>
So within component id="A", a user selects a value from drop down menu, bean captures it and dynamically show or hide component id="C" or "D" based on the value.
First time try, I didn't have any h:panelGroup tags. I used rendered attribute directly from p:tab component however I realized that unless I refresh the entire page, the bean.checkValue wouldn't know latest value captured. By reading many articles in this forum, I realized I have to wrap it with h:panelGroup which in turn worked by showing either h:panelGroup "C" or "D" based on the value selected from p:tab tag with id="A".
However the contents of f:facet tag is not visible anymore. It has html table tag which contains h:outputText with static value and p:graphicImage. I am not sure why and hope someone can solve this mystery.
Update:
Thanks to Arthur. I was able to fix the issue with his help. I paste here code that performs expected output.
<p:tabView id="view">
<p:tab id="A">
...
<p:ajax event="change" update="view" listener="#{bean.captureValue}"/>
</p:tab>
<p:tab id="B" titleStyleClass="x">
<f:facet name="title">
<ui:fragment rendered="#{bean.checkValue eq 'Yes'}"/>
<table>...</table>
</ui:fragment>
</f:facet>
<ui:fragment rendered="#{bean.checkValue eq 'Yes'}"/>
<div>...</div>
</ui:fragment>
<f:facet name="title">
<ui:fragment rendered="#{bean.checkValue eq 'No'}"/>
<table>...</table>
</ui:fragment>
</f:facet>
<ui:fragment rendered="#{bean.checkValue eq 'No'}"/>
<div>...</div>
</ui:fragment>
</p:tab>
</p:tabView>
Facets are representing a named section within a container component. Container for your facets are in both cases <h:panelGroup> and this component doesn't define any facet which you could use. As you don't provide in your sample code any name for the facet (which is mandatory) I only assume that maybe you would like to use a title facet for a tab, as <p:tab> component define facet named "title". Then it should look like
<p:tab id="B">
<f:facet name="title" >
<h:outputText value="Test1" rendered="#{bean.checkValue}"/>
<h:outputText value="Test2" rendered="#{!bean.checkValue}"/>
</f:facet>
</p:tab>
, so you implement rendering logic inside facet value (you decide which title would be displayed. This logic could be also moved to backing bean. Keep in mind that in primefaces sometimes components doesn't handle very well and you could try then use them as an attribute instead of facets as stands in this post
It is also possible that you misunderstand meaning of facets. The best way to explain them are the facets defined i component. Authors of this component wanted to provide for users possibility to define header and footer of datatable. Then you, as a jsf user can compose header for instance, from other different components. You could also check this post where facets are also explained.
One more thing to add is that using <h:panelGroup rendered="#{bean.checkValue}"/> for render logic is considred as bad pattern as it is going to produce a <span> element in your code. Instead you should use <ui:fragment rendered="#{bean.checkValue}"/> which is intended for rendering logic and it won't produce any additional html code

Fire AJAX twice from same component (simultaneously)

Well, I want to fire AJAX from one component but for two destinations, let some code clear out what I mean with that :
<p:growl id="growl" showDetail="true" sticky="true" />
<p:inputText value="#{someBean.someProperty}" >
<f:ajax event="blur" render="growl" listener="#{someBean.someListenerMethod}"/>
<f:ajax event="blur" render="updatable" />
</p:inputText>
<h:outputText value="#{someBean.someProperty}" id="updatable" />
So once the blur event occures, the <h:outputText> and the <p:growl> will be "AJAXed" (in primefaces tongue : updated). I had this example in mind and anther one that replaces the second <f:ajax> with an update attribute in <p:inputText>, but neither done me good.
Hopefully, you're going to know better and aid me solving this out, thanks in advance.
You can add more than one item inside the render attribute :
<f:ajax event="blur" render="growl updatable" listener="#{someBean.someListenerMethod}"/>

Primefaces components to update when commandButton is clicked

Lets say we have button
<h:form>
<p:commandButton id="refreshButton" value="refresh all depending components"/>
</h:form>
Along the way I will add components that should be updated when the button is clicked. So using the update="text1,text2" will not suffice, as text3 might be added later on and shouldn't require changes to the refresh button.
<h:outputText id="text1" value="{bean.someValue1}></h:outputText>
<h:outputText id="text2" value="{bean.someValue2}></h:outputText>
... and later ...
<h:outputText id="text3" value="{bean.someValue3}></h:outputText>
What I want to do is to bind the components to the button, rather than the button having dependencies to the components
What you're asking is not possible. As least, not using the standard ways in the view.
But what is possible is to reference a common parent instead.
<p:commandButton ... update="texts" />
...
<h:panelGroup id="texts">
<h:outputText id="text1" ... />
<h:outputText id="text2" ... />
...
<h:outputText id="text3" ... />
</h:panelGroup>
Depending on the concrete functional requirement, which isn't clear from the question, there may be better solutions. But if it boils down to laziness and/or avoiding to "forget" to change the button, then I'm afraid that there's no magic fix.
I did a a temporary quickfix by using
<p:outputPanel autoUpdate="true">
<h:outputText id="text3" ... />
<p:outputPanel />
Guess it performance wise is not perfect, as it will be updated on all ajax events and not just the ones I'm interested in. But luckily this component is interested in all of them any ways, so it is not a problem atm.

JSF2: Form ajax action makes another form's view state to be lost

I have a simple page consisting of two forms. They cannot be displayed simultaneously (one toggles the other). Here is the code:
<h:body>
<ui:composition template="/elements/templateWithMenu.xhtml">
<ui:define name="content">
<p:dialog id="question1DialogId" widgetVar="question1Dialog" resizable="false" closable="false" visible="true">
<h:panelGroup id="questionStep1Group">
<h:form id="questionStep1Form" rendered="#{newPoll2.displayQuestionStep1}">
<h:commandLink value="next" action="#{newPoll2.questionStep1Completed()}" class="btn" >
<f:ajax execute="#form" render=":questionStep2Form :questionStep1Group :questionStep2Group"/>
</h:commandLink>
</h:form>
</h:panelGroup>
<h:panelGroup id="questionStep2Group">
<h:form id="questionStep2Form" rendered="#{newPoll2.displayQuestionStep2}">
<h:commandLink value="cancel" action="#{newPoll2.questionStep2Cancelled()}" class="btn" >
<f:ajax execute="#form" render=":questionStep1Form :questionStep1Group :questionStep2Group" />
</h:commandLink>
</h:form>
</h:panelGroup>
</p:dialog>
</ui:define>
</ui:composition>
</h:body>
questionStep1Completed() and questionStep2Cancelled() simply toggle the booleans used in rendered attribute.
The problem is with the view states. When the page is first loaded, clicking on "next" will work, and it will be replaced with the "cancel" link. But when I click on the "cancel" link, it needs to be clicked twice in order for it to be replaced with with the "next" link. I can see that the first click makes the request with no view state, and the second (successful) one makes a request with it.
I saw this question, and this link, and as you can see, I've added form ids in the render attribute, but it still doesn't work. Any ideas?
Thanks
You're conditionally rendering the forms themselves and hence the other form isn't physically available in the HTML DOM tree at the moment the ajax request is been prepared. If you wrap the form's content in another <h:panelGroup> and move the rendered attribute to there, then it ought to work.

Resources