AJAX call clears values in unrelated controls - ajax

I'm using RichFaces' a4j:support to toggle the visibility of some controls on the page. However, when the h:selectOneRadio button rdoRequestType is changed, it clears the values of the txtLibraryServerNumber and other controls in the a4j:outputPanel with ID "media". Why would one AJAX call on a page interfere with a different AJAX panel?
I've tried using the "process" attribute on the a4j:support tag on the selectOneRadio so it writes the values of the text boxes in the other panel to the Seam bean, but that has no effect. What the heck am I doing wrong? Help! I'm losing my mind!!
<h:selectOneRadio value="#{webencode.requestType}"
id="rdoRequestType" styleClass="radio" style="width:295px" layout="pageDirection" >
<f:selectItem itemValue="program" itemLabel="Series or Individual Program"/>
<f:selectItem itemValue="promo" itemLabel="Promo" />
<f:selectItem itemValue="specific" itemLabel="Specific Format Encoding Request"/>
<a4j:support ajaxSingle="true" event="onclick" reRender="program" process="txtLibraryServerNumber,txtDigitalMediaFileName"/>
</h:selectOneRadio>
<a4j:outputPanel id="program" ajaxRendered="true">
<s:span rendered="#{('program' == webencode.requestType || 'promo' == webencode.requestType) ? true : false}">
<h:selectOneMenu value="#{webencode.seriesId}" id="lstSeriesName">
<f:selectItems value="#{webencode.programItems}"/>
</h:selectOneMenu>
</s:span>
<s:span rendered="#{'specific' == webencode.requestType ? true : false}">
<h:selectOneMenu value="#{webencode.arrVideoEncodings.get(0).videoEncoding}"
id="lstSpecificVideoEncoding1" style="width:295px;">
<f:selectItems value="#{webencode.videoEncodingItems}"/>
</h:selectOneMenu>
</s:span>
</a4j:outputPanel>
<h:selectOneMenu value="#{webencode.inputMediaType}"
id="lstInputMediaType">
<f:selectItems value="#{webencode.inputMediaTypeItems}"/>
<a4j:support ajaxSingle="true" event="onchange" reRender="media" process="lstSeriesName,lstSpecificVideoEncoding1"/>
</h:selectOneMenu>
<a4j:outputPanel id="media" ajaxRendered="true">
<s:span rendered="#{'Tape Library # or Server ID #' == webencode.inputMediaType ? true : false}">
<h:inputText id="txtLibraryServerNumber"
value="#{webencode.libraryServerNumber}" maxlength="50" />
</s:span>
<s:span rendered="#{'Digital Media File Name' == webencode.inputMediaType ? true : false}">
<h:inputText id="txtDigitalMediaFileName"
value="#{webencode.digitalMediaFileName}" maxlength="195" /><br />
</s:span>
</a4j:outputPanel>

If you have the UpdateMode property of the panel set to "always" it will update with any postback occurs. If you set it to "conditional" it will only update when one of it's own triggers causes a postback.
I don't know if this would clear your controls, but it is a possible answer to why one panel is effecting another.

What is the scope of your Webencode bean? It will have to be Page or longer or your values will be lost with each call. Remember that if you don't specify a scope it defaults to Request and each Ajax call is a Request.
Your media panel is always being refreshed as you've specified it with the ajaxRendered attribute which is like saying "even if I'm not asked to be reRendered, reRender me always anyway." Unless you have a good reason to use ajaxRendered (eg. something that is always rendered like status messages), then you are better off starting with explicity specifying what to reRender.
The process attribute isn't necessary here - get rid of it.
Cheers,
D

Found the solution: Very strange, but on the server, which is running Apache with JBoss, it needs to have the limitToList attribute set to true:
<a4j:support ajaxSingle="true" event="onchange" reRender="media"
limitToList="true"/>
This ensures only the control indicated (in this case "media") is re-rendered. Still don't know why it's required on the server but not on the localhost. Gotta be something with Apache and how it communicates with JBoss, but not sure.

Related

Why are fields reset after ajax update with JSF

on a form : i have one page include two tab.
Tab rendered some boolean values.
e)
after first page i have command buton . Yes or no( its reset booelan value)
if ı click yes second page rendered true and page show but all values reset. All data reset ? What is problem ? How can i solve this.
All code is here :http://pastebin.com/Ffi33hdw
Uptade buton line 287 .
<h:selectOneRadio id="fikirorProje" required="true" value="#{ideaBean.newIdea.fikirProje}"
enabledClass="labelNormalRadio" disabled="#{ideaBean.createdIdea}"
requiredMessage="Bu alan boş bırakılamaz.">
<f:selectItem itemValue="#{false}"
itemLabel="Hayır" uptade="butonThree"/>
<f:selectItem itemValue="#{true}" itemLabel="Evet"/>
<p:ajax event="change" update="addIdeaForm" />
<p:ajaxStatus onstart="PF('status').show()" onsuccess="PF('status').hide()"/>
</h:selectOneRadio>
thans for answering
Theprocess attribute of p:ajax defaults to #this, so in the change event of your h:selectOneRadio your form is not being fully process which means that the ideaBean's properties will not be updated, (check more info about how update/process work here). Add process="#form" to your ajax event <p:ajax event="change" update="addIdeaForm process="#form" /> and it should work

Mutually exclusive input fields with JSF and PrimeFaces

I have a PrimeFaces application where I would like to make two input text fields mutually exclusive: the user should fill either field, but not both.
In the following example, the user could search contacts either by phone number or by email.
<h:form>
<h:outputLabel>Phone Number:
<h:inputText id="phoneInput" value="#{contactSearch.phone}"
disabled="#{not empty contactSearch.email}">
<p:ajax event="keyup" update="emailInput"/>
</h:inputText>
</h:outputLabel>
<h:outputLabel>Email Address:
<h:inputText id="emailInput" value="#{contactSearch.email}"
disabled="#{not empty contactSearch.phone}">
<p:ajax event="keyup" update="phoneInput"/>
</h:inputText>
</h:outputLabel>
<!-- Possibly other fields... -->
<h:commandButton value="Search" action="#{contactSearch.search}"/>
</h:form>
Is this the proper way to do it? I am concerned about:
Possible "deadlock" issues, where both fields end up being disabled
The whole form being submitted and/or valdiated in the Ajax request, when I just would like to update the disabled state of the input field
Missing some predefined PrimeFaces control which does all the work :)
This is not trivial in standard JSF. JSF utility library OmniFaces has a validator for exactly this purpose, the <o:validateOne>.
<h:inputText id="email" ... />
<h:inputText id="phone" ... />
<o:validateOne components="email phone" />
However, in UX perspective, you'd better redesign your form to provide a single UISelectOne component to select the type and a single UIInput field to enter the value. E.g.
<h:selectOneRadio ... value="#{bean.type}">
<f:selectItem itemValue="email" />
<f:selectItem itemValue="phone" />
</h:selectOneRadio>
<h:inputText ... value="#{bean.value}" />
Update: as server side validation is not affordable and you'd really like to disable the the other without making much ajax traffic, your only bet is using pure JavaScript/jQuery for the job (if necessary in combination with server side validation as fallback).
Here's a generic jQuery based approach:
<h:inputText styleClass="onlyone" a:data-onlyone="groupName" />
<h:inputText styleClass="onlyone" a:data-onlyone="groupName" />
...
$(document).on("input", ":input.onlyone", function() {
var $this = $(this);
var $others = $("[data-onlyone='" + $this.data("onlyone") + "']").not($this);
$others.val(null).attr("disabled", !!$this.val());
});
The data-onlyone value should represent the group name, so you can have multiple of "only one" inputs throughout the document.

JSF Ajax reset previously rendered input component values?

I have a small (but vital) problem with JSF and ajax. The form is here:
<h:form>
<h:panelGrid id="pg1" columns="2">
<h:outputText value="Type: "/>
<h:selectOneMenu id="selectOne" value="#{personBean.type}">
<f:selectItems value="#{listBean.personTypes}"/>
<f:ajax event="valueChange" render="pg2"/>
</h:selectOneMenu>
</h:panelGrid>
<h:panelGrid id="pg2" columns="2">
<h:outputText value="Really bad?" rendered="#{personBean.type=='BAD'}"/>
<h:selectBooleanCheckbox id="checkbox" value="#{personBean.reallyBad}" rendered="#{personBean.type=='BAD'}">
<f:ajax event="click"/>
</h:selectBooleanCheckbox>
</h:panelGrid>
<h:commandButton value="Ajax Submit" action="#{personBean.printValues}">
<f:ajax execute="#form"/>
</h:commandButton>
</h:form>
The PersonBean is a simple bean with an enum PersonType that has two values: NICE, BAD and a Boolean called reallyBad. The ListBean returns the enum values in a list to populate the selectOneMenu.
Basically when I select BAD the panel for the boolean checkbox is rendered where I can tick it to say a person is reallyBad. I can then submit the form if I wish. The problem is when I tick the checkbox and then select NICE again, the checkbox is still ticked even though it is not rendered. So when I submit my form the person can be NICE and reallyBad, which doesn't make sense.
Rather than having to select BAD again to uncheck the box, is their a way that I can reset the checkbox and its input value to false when NICE is selected? I'm a bit of a noob to ajax with JSF! Thanks.
ps. I am printing the values of the two inputs on submit with the commandButtons action to verify the results...
You need to manually clear the checkbox when you change the menu.
<f:ajax listener="#{personBean.setReallyBad(false)}" render="pg2" />
By the way, the both <f:ajax event> values as you've in your code are the default values already. Just omit them.

How to let validation depend on the pressed button?

I have created form and I want to show previous existing items on a table while a new one is creating. I'd like to show matching items as form is filling up. But when I try to filter the list without having the form completed, the validation messages appear and the table doesn't get updated.
Don't know if it's possible, but what I want to do something like this:
<h:form id="form">
<h:outputText value="Name: "/>
<p:inputText value="#{itemsBean.name}" id="name" required="true"/>
<br/>
<h:outputText value="Description: "/>
<p:inputText value="#{itemsBean.description}" id="description" required="true"/>
<p:commandButton value="Save" update="form" actionListener="#{itemsBean.save}"/> //validate and save
<p:commandButton value="Filter" update="form" actionListener="#{itemsBean.updateItemsList}"/> //don't validate, and update the table.
<p:dataTable id="list" value="#{itemsBean.itemsList}" var="item">
<p:column>
<h:outputText value="#{item.name}"/>
</p:column>
<p:column>
<h:outputText value="#{item.description}"/>
</p:column>
</p:dataTable>
</h:form>
I'm very new to JSF.
I understand that you want to filter based on the name input field. The <p:commandButton> sends by default an ajax request and has a process attribute wherein you can specify which components you'd like to process during the submit. In your particular case, you should then process only the name input field and the current button (so that its action will be invoked).
<p:commandButton process="#this name" ... />
The process attribute can take a space separated collection of (relative) client IDs of the components, wherein #this refers to the current component. It defaults in case of <p:commandButton> to #form (which covers all input fields of the current form and the pressed button), that's why they were all been validated in your initial attempt. In the above example, all other input fields won't be processed (and thus also not validated).
If you however intend to skip the required validation for all fields whenever the button in question is been pressed, so that you can eventually process multiple fields which doesn't necessarily need to be all filled in, then you need to make the required="true" a conditional instead which checks if the button is been pressed or not. For example, let it evaluate true only when the save button has been pressed:
<p:inputText ... required="#{not empty param[save.clientId]}" />
...
<p:inputText ... required="#{not empty param[save.clientId]}" />
...
<p:commandButton binding="#{save}" value="Save" ... />
This way it won't be validated as required="true" when a different button is pressed. The trick in the above example is that the name of the pressed button (which is essentially the client ID) is been sent as request parameter and that you could just check its presence in the request parameter map.
See also:
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
I Have tested this with non-ajax submits:
<p:inputText ... required="#{not empty param.includeInSave1}" />
...
<p:inputText ... required="true" />
...
<p:commandButton value="Save1" ajax="false">
<f:param name="includeInSave1" value="true" />
</p:commandButton>
<p:commandButton value="Save2" ajax="false" />
The first input is required validated only on Save1 button submit.
Additionally to the BalusC answer (very useful and complete) I want to add that when you use a <h:commandButton /> it will validate (required, custom validations) all the fields in the <h:form /> where the command button is located, therefore when you need to use more than one command button you could consider that it is a good practice to use different <h:form /> to different responsibilities to avoid unexpected behavior in submit actions of the command buttons.
It is well explained in a BalusC answer: Multiple h:form in a JSF Page
If your form has validations and you do not update the <h:form /> or you do not show messages, you could get a headache thinking that the <h:commandButton /> is not firing your action, but likely is a validation problem that has not been shown.
Change your filter commandbutton like this to ignore validation:
<p:commandButton value="Filter" update="list" actionListener="#{itemsBean.updateItemsList}" process="#this"/>
EDIT:
The related post on SO, I think this will solve your issue too
JSF 2.0: How to skip JSR-303 bean validation?

JSF AJAX Request not working with hx:panelDialog

I wrote the following code,
<h:form id="PrefForm" >
<hx:commandExButton id="preferenceButton" type="button" style="align:right;" value="#{nls.preferenceLink }" title="#{nls.preferenceLinkTitle}" >
<hx:behavior event="onclick" behaviorAction="get" targetAction="prefPanelGroup"></hx:behavior>
<hx:behavior event="onclick" behaviorAction="show;stop" targetAction="preferenceSet"></hx:behavior>
</hx:commandExButton>
<hx:panelDialog id="preferenceSet" type="modal" styleClass="panelDialog" title="#{nls.preferenceDialogTitle}" >
<h:outputText styleClass="panelStartMessage" style="display:block;" value="#{nls.preferenceDialogWindowText}" />
<h:panelGroup id="prefPanelGroup" rendered="#{neoReport.hasSelectItem }" style="display:block;width:300px;height:360px;overflow:auto;" >
<hx:ajaxRefreshRequest id="refreshform" />
<h:selectManyCheckbox value="#{neoReport.selectedItems}" layout="pageDirection">
<f:selectItems value="#{neoReport.selectItems}" />
</h:selectManyCheckbox>
</h:panelGroup>
<hx:panelBox id="noCommandWindow" rendered="#{!neoReport.hasSelectItem }" style="display:block;width:300px;height:50px;" layout="lineDirection">
<h:outputText styleClass="outputText" id="cmdInfo" value="#{nls.noCommands}" />
</hx:panelBox>
<h:panelGroup id="buttonBox1" styleClass="panelStartBox" >
<hx:commandExButton id="submitPref" styleClass="commandExButton" type="submit" value="#{nls.submit}" action="#{neoReport.action}">
<hx:behavior event="onclick" behaviorAction="hide" targetAction="preferenceSet" id="behaviorSubmitPref" />
</hx:commandExButton>
<hx:commandExButton id="CancelPref" styleClass="commandExButton" type="submit" value="#{nls.cancel}" action="neoReport">
<hx:behavior event="onclick" behaviorAction="hide" targetAction="preferenceSet" id="behaviorCancelPref" />
</hx:commandExButton>
</h:panelGroup>
</hx:panelDialog>
</h:form>
Basic idea behind this code is to have a button on the page,when user click,it should get the latest data from bean( by extracting a file,which is continuously getting updated) and fill the List object in databean,so that h:selectManyCheckBox can render that. So i added a behavior with the commandExButton,so that it will get the new data and it should render the latest options in selectManyCheckBox. BUT out of these two hx:behavior,only the first one is working,its calling the getter function of
<f:selectItems value="#{neoReport.selectItems}"
but its not rendering the panelDialog further.If i remove the behavior for "get" it will show the panel dialog but not with the updated data. So i am not able to find out,what exactly wrong i am doing here.Can anyone help?
First of all I don't know what type of tag library is this. You should point it out in the tags and/or in the question.
You should have only one <hx:behavior> tag, which does all the job for you. If doing so, you should have a method that calls all three methods. Is it possible with these tags to rerender multiple components with AJAX - like targetAction="prefPanelGroup, preferenceSet"?
As far as I know, rerendering preferenceSet will cause prefPanelGroup to rerender too, so it's pointless to rerender separately.
Also, rerendering prefPanelGroup will work only by telling the <hx:behavior> tag a more precise id, like "PrefForm:prefPanelGroup".
Hope this helps,
Daniel

Resources