one requiredMessage for 2 "h:selectOneMenu"s - jsf

I want one requiredmessage for two h:selectOneMenu components, that is when a user submits the form if one of those selects values is not null, the bean method should be called, otherwise(both of them null) : I should tell him to select at least one, is it possible? or do I have to use JS.
Thanks in advance,

I'd use the OmniFaces validateOne validator for this or the validateOneOrMore if filling both is allowed too.
Code example from their site:
<h:form>
<h3>Please fill out only one of two fields</h3>
<o:validateOne id="one" components="foo bar" />
<h:panelGrid columns="3">
<o:outputLabel for="foo" value="Foo" />
<h:inputText id="foo" />
<h:message for="foo" />
<o:outputLabel for="bar" value="Bar" />
<h:inputText id="bar" />
<h:message for="bar" />
<h:panelGroup />
<h:commandButton value="submit">
<f:ajax execute="#form" render="#form" />
</h:commandButton>
<h:panelGroup>
<h:message for="one" />
<h:outputText value="OK!" rendered="#{facesContext.postback and not facesContext.validationFailed}" />
</h:panelGroup>
</h:panelGrid>
</h:form>

Related

passing the selected object from list of objects that each one has its own button

I’m working on a web-app that displays list of objects, each object has its own modal when clicked inside the modal there are two dropdown menus and a button that is supposed to call a method add in a bean, to perform an action and add the selected object while taking three values, selected object, selected two items from the two drop downs and spinner’s value.
<ui:repeat value="#{ViewTeacher.teacherList}" var="teacher"
varStatus="status">
<h:panelGroup layout="block" styleClass="name">
<p>#{teacher.name}</p>
</h:panelGroup>
<br />
<br />
<a onclick="viewModal(#{status.index})" class="btn btn-success">view</a>
<h:panelGroup id="modal" layout="block" class="modal"
style="max-width: 44em;" tabindex="1">
<h:panelGroup class="modal-content" layout="block">
<span class="close" onclick="modClose()">×</span>
<h:outputText styleClass="description" value="#{teacher.name}" />
<br />
<br />
<br />
students
<h:selectOneMenu value="ok" class="form-control">
<f:selectItems value="#{teacher.students}" var="s"
itemValue="#{s.id}" itemLabel="#{s.name}" />
</h:selectOneMenu>
classes
<h:selectOneMenu value="ok" class="form-control">
<f:selectItems value="#{teacher.classes}" var="c"
itemValue="#{c.id}" itemLabel="#{c.name}" />
</h:selectOneMenu>
<br />
<h:panelGroup layout="block" styleClass="form-group">
<p:spinner min="1" max="10" />
</h:panelGroup>
<h:commandButton id="submitButton" styleClass="btn btn-success" value="ADD">
<!—-this is the button that is supposed to take the values
</h:commandButton>
<a onclick="modClose()" class="btn btn-success">CANCEL</a>
</h:panelGroup>
</h:panelGroup>
</ui:repeat>
I tried :
<f:param name="name1" value="China" />
But the fact that param’s name will get repeated, will make it the same all the time and might be set to the latest object retrieved,
Any recommendation?
UPDATE:
<p:commandLink styleClass="btn btn-success" process="#this"
onclick="viewModal(#{status.index});">
<h:outputText value="ADD" />
<f:setPropertyActionListener
value="#{teacher.id}" target="#{ViewTeacher.selectedTeacher}" />
</p:commandLink>
Made this change to pass the teacher's id but it's still null in the bean
First of all, having a separate modal for each object isn't a good idea. You can achieve (what you are trying) by:
1). Adding a property (with its getter and setter) in bean for selected object.
2). Place single modal (<p:dialog with id="modal" and widgetVar="modal" attributes) outside ui:repeat to display data from selected object.
3). Set selected object on clicking view link, update and display modal, using:
<p:commandLink styleClass="btn btn-success" process="#this" update="modal"
onclick="PF('modal').show();">
<h:outputText value="View" />
<f:setPropertyActionListener
value="#{teacher}" target="#{ViewTeacher.selectedTeacher}" />
</p:commandLink>
Here, f:setPropertyActionListener will be setting your selected modal in bean and thus it will become available in your action listener.
Update: Change the code as following:
<ui:repeat value="#{ViewTeacher.teacherList}" var="teacher" varStatus="status">
<h:panelGroup layout="block" styleClass="name">
<p>#{teacher.name}</p>
</h:panelGroup>
<p:commandLink styleClass="btn btn-success" process="#this" update="modal"
oncomplete="PF('modal').show();">
<h:outputText value="view" />
<f:setPropertyActionListener
value="#{teacher}" target="#{ViewTeacher.selectedTeacher}" />
</p:commandLink>
</ui:repeat>
<p:dialog id="modal" widgetVar="modal" header="Edit Teacher" modal="true"
showEffect="fade" hideEffect="fade" resizable="false" closeOnEscape="true"
styleClass="teachers-dialog">
<h:outputText styleClass="description" value="#{ViewTeacher.selectedTeacher.name}" />
<br />
<br />
<br />
students
<h:selectOneMenu value="#{ViewTeacher.selectedStudentId}" class="form-control">
<f:selectItems value="#{ViewTeacher.selectedTeacher.students}"
var="s" itemValue="#{s.id}" itemLabel="#{s.name}" />
</h:selectOneMenu>
classes
<h:selectOneMenu value="#{ViewTeacher.selectedClassId}" class="form-control">
<f:selectItems value="#{ViewTeacher.selectedTeacher.classes}"
var="c" itemValue="#{c.id}" itemLabel="#{c.name}" />
</h:selectOneMenu>
<br />
<h:panelGroup layout="block" styleClass="form-group">
<p:spinner value="#{ViewTeacher.spinnerValue}" min="1" max="10" />
</h:panelGroup>
<h:commandButton id="submitButton" styleClass="btn btn-success" value="ADD">
</h:commandButton>
</p:dialog>
Where selectedTeacher, selectedStudentId, selectedClassId, spinnerValue are properties from your ViewTeacher bean.

using ID from a selected item in jsf

I want to use the ID of selected item from the list below to use it in other function, how can I do it please , am using JSF;
I have tried many times but in vain !! please help
here is my code in jsf:
<p:panelGrid columns="2" style="width:60% ; padding-left:25%"
layout="grid">
<p:dataTable var="convert"
value="#{convertirDeviseCtr.listeDevise}" style="width:70%"
id="convertir">
<f:facet name="header">Liste des devises</f:facet>
<p:column selectionMode="single">
<h:outputText value=" " />
<h:outputText value=" " />
<p:graphicImage value="/images/flags/#{convert.libSiglDev}.png"
id="img" style="width:20px ; height:20px" />
<h:outputText value=" " />
<h:outputText value=" " />
<h:outputText value="#{convert.libDevDev}" />
</p:column>
</p:dataTable>
<p:panel style="padding-top:40%">
<br />
<h:outputText value="Saisir montant :" />
<h:outputText value=" " />
<p:keyboard id="image" value="#{keyboardView.value8}"
showMode="button" buttonImageOnly="true"
buttonImage="/images/icons/keyboardpencil.png" keypadOnly="true"
style="width:150px ; height:20px" />
<br />
<br />
<p:selectOneButton value="" style="margin-left:35%">
<f:selectItem itemLabel="Achat" itemValue="A" />
<f:selectItem itemLabel="Vente" itemValue="V" />
</p:selectOneButton>
<br />
<br />
<p:commandButton value="Convertir" icon="ui-icon-refresh"
style="margin-left:40%"></p:commandButton>
<br />
<br />
<p:outputLabel>Resultat :</p:outputLabel>
<p:inputText value=""></p:inputText>
</p:panel>
</p:panelGrid>
thanks in advance;
You must use the selection attribute of <p:dataTable>. The value of the selection attribute must be a property of a backing bean where the selected value will be stored. For example:
...
<p:dataTable var="convert"
value="#{convertirDeviseCtr.listeDevise}" style="width:70%"
id="convertir" selection="#{someController.selectionProperty}">
...
More information about <p:dataTable> tag and the different types of selection modes:
http://www.primefaces.org/showcase/ui/data/datatable/selection.xhtml

Popuppanel stays open after validation

I have a rich faces popuppanel that I want to keep open until all validation is done. For now I just have a required attribute on the address. If the address is missing and the Submit button is clicked the popuppanel should stay open until the address is entered which it does. However when the user enters an address the form sends the email as it should but the page stays open. I need the popuppanel to close when the required field is entered.
<rich:popupPanel id="addressModalPanel" header="Change Billing Address" modal="true" domElementAttachment="form" width="450" height="400">
<h2>Submit Change of Billing Address</h2>
<h:outputLabel value="Enter changes to your company's billing address in the fields below and then click Submit" /><br></br>
<h:panelGrid columns="2" >
<h:outputLabel value="Company Name: "/>
<h:inputText value="#{supplieraddress.supplierAddress.supplierName}" disabled="true" />
<h:outputLabel value="Vendor Number: " />
<h:inputText value="#{supplieraddress.supplierAddress.id}" disabled="true"/>
<h:outputLabel value="Address: " />
<h:inputText id="add1" value="#{supplieraddress.supplierAddress.add1}" required="true" requiredMessage="Address is required" style="width:200px" />
<h:outputLabel value=""/>
<h:inputText value="#{supplieraddress.supplierAddress.add2}" style="width:200px" />
<h:outputLabel value=""/>
<h:inputText value="#{supplieraddress.supplierAddress.add3}" style="width:200px" />
<h:outputLabel value="City: " />
<h:inputText id="city" value="#{supplieraddress.supplierAddress.city}" />
<h:outputLabel value="State: " />
<h:inputText id="state" value="#{supplieraddress.supplierAddress.state}" style="width:50px" />
<h:outputLabel value="Zip: " />
<h:inputText id="zip" value="#{supplieraddress.supplierAddress.zip}" style="width:50px" />
<h:outputLabel value="Country (If not US): " />
<h:inputText id="country" value="#{supplieraddress.supplierAddress.country}" style="width:50px" />
<a4j:commandButton id="submit" value="Submit" actionListener="#{supplieraddress.billingAddressEmail()}" oncomplete="if(#{!empty add1}) #{rich:component('addressModalPanel')}.hide()" >
</a4j:commandButton>
<h:commandButton value="Close" >
<rich:componentControl event="click" target="addressModalPanel" operation="hide" />
</h:commandButton>
<a4j:outputPanel ajaxRendered="true">
<rich:message for="add1" style="color:red"/>
</a4j:outputPanel>
</h:panelGrid>
</rich:popupPanel>
if(#{!empty add1}) looks like a misuse of the empty operator; empty is to be applied to Collections only. What you should be using instead
<a4j:commandButton id="submit" value="Submit" actionListener="#{supplieraddress.billingAddressEmail()}" oncomplete="if(!#{facesContext.validationFailed}) #{rich:component('addressModalPanel')}.hide()" >
Where facesContext.validationFailed is a convenience method that checks the validation status of the current JSF context

<o:massAttribute> affects another components in same <h:panelGrid>

I'm using the new version of OmniFaces 1.8.1, and particullary I start to use the new tag: <o:massAttribute>. Basically, I have the following form with conditionally rendered and disabled fields:
<h:form id="formABMProducto">
<h:panelGrid id="datosProducto" columns="4">
<o:massAttribute name="rendered" value="#{cc.attrs.page != 'baja'}">
<h:outputLabel for="codigo" ... />
<h:inputText id="codigo" ... />
<rich:message for="codigo" />
<h:panelGroup />
</o:massAttribute>
<o:massAttribute name="rendered" value="#{cc.attrs.page eq 'baja'}">
<h:outputLabel for="codigo" .../>
<rich:autocomplete id="codigoProducto" ... />
<rich:message for="codigo" />
<h:panelGroup />
</o:massAttribute>
<o:massAttribute name="disabled" value="#{cc.attrs.disableComponents}">
<h:outputLabel for="nombre" ... />
<h:inputTextarea id="nombre" ... />
<rich:message for="nombre" />
<span />
<h:outputLabel for="descripcion" ... />
<h:inputTextarea id="descripcion" ... />
<rich:message for="descripcion" />
<span />
</o:massAttribute>
<h:outputLabel value="#{msgs['producto.abm.panel.proveedor.tipo']}" for="CmbTipoProveedor"/>
<rich:select id="CmbTipoProveedor" ... />
<rich:message for="CmbTipoProveedor" />
<a4j:commandButton ... />
</h:panelGrid>
</h:form>
However, when I open the page, the third <o:massAttribute> is also disabling another input fields codigo and codigoProducto. I think this isn't the expected behaviour.
Indeed, this was a bug. The <o:massAttribute> got applied on all children of the parent UIComponent instead of only those contained in the tag. It would theoretically have worked when you've wrapped each <o:massAttribute> in its own UIComponent like <h:panelGroup> or so. However, this is clearly not an option in case of a <h:panelGrid> wherein you'd like to put the children each in its own column.
I reproduced your problem, filled issue 51 about this bug and fixed it in the current 2.0 snapshot. Please give it a try and sorry for any inconvenience.

PrimeFaces button in Tab Doesn't Navigate

I'm developing this project using JSF 2.0, NetBeans 6.9.1, GlassFish 3.1, Mojarra 2.0.3, and PrimeFaces 2.2-RC2.
My question is similar to this question, but even though I was able to make one of my buttons work, the other one does not. Here's my situation: I have a dataTable with a column containing two links, one to edit line data, one to view line data. Clicking either the "Edit" or "View" link takes you to a detail page with <h:panelGrid> components inside <p:tabView> components. My detail page has two <p:tabView> components, one for editing, one for just viewing data. Which one you see depends on the <c:if> statements. The button in the first <p:tabView> on the page (by that I mean first working your way down from the top) works as I would like it to, this happens to be the "Edit" component. The button in the other <p:tabView> does not work. I set up break points and went through the debugger, the second button doesn't seem to fire an ActionEvent regardless of what I try. Here's my code for the page:
<ui:define name="metadata">
<f:metadata>
<f:viewParam name="id" value="#{userDetailBean.selectedUserId}" />
<f:viewParam name="action" value="#{userDetailBean.view}" />
</f:metadata>
</ui:define>
<ui:define name="main_base_content_top">
<h:form>
<p:toolbar>
<p:toolbarGroup align="left">
<h:commandButton value="Return to User List" action="user_grid" />
</p:toolbarGroup>
</p:toolbar>
</h:form>
</ui:define>
<ui:define name="main_base_content">
<c:if test="#{empty userDetailBean.view}">
<h:form>
<table align="center">
<tr>
<td>
<p:tabView>
<p:tab title="#{msgs.UserDetailTabTitle}">
<h:panelGrid columns="4">
<h:outputLabel value="#{msgs.UserDetailFirstName}" for="fname" />
<h:inputText id="fname" value="#{userDetailBean.firstName}" />
<h:outputLabel value="#{msgs.UserDetailJobTitle}" for="jtitle" />
<h:inputText id="jtitle" value="#{userDetailBean.jobTitle}" />
<h:outputLabel value="#{msgs.UserDetailLastName}" for="lname" />
<h:inputText id="lname" value="#{userDetailBean.lastName}" />
<h:outputLabel value="#{msgs.UserDetailEmployeeId}" for="empid" />
<h:inputText id="empid" value="#{userDetailBean.id}" />
<h:outputLabel value="#{msgs.UserDetailDateOfHire}" for="doh" />
<h:inputText id="doh" value="#{userDetailBean.DOH}" />
<h:outputLabel value="#{msgs.UserDetailLocation}" for="location" />
<h:inputText id="location" value="#{userDetailBean.location}" />
<h:outputLabel value="#{msgs.UserDetailStatus}" for="status" />
<h:inputText id="status" value="#{userDetailBean.status}" />
<h:inputHidden /> <h:inputHidden /> <h:inputHidden /> <h:inputHidden /> <h:inputHidden />
<h:outputLabel value="#{msgs.UserDetailComments}" for="comments" />
<h:inputTextarea id="comments" value="#{userDetailBean.comments}" />
<h:inputHidden />
<p:commandButton ajax="false" action="#{userDetailBean.submitChanges()}" value="Submit Changes" />
</h:panelGrid>
</p:tab>
</p:tabView>
</td>
</tr>
</table>
</h:form>
</c:if>
<c:if test="#{! empty userDetailBean.view}">
<h:form>
<table align="center">
<tr>
<td>
<p:tabView>
<p:tab title="#{msgs.UserDetailViewTabTitle}">
<h:panelGrid columns="4">
<h:outputLabel value="#{msgs.UserDetailFirstName}" for="fname" />
<h:outputText id="fname" value="#{userGridBean.selectedUser.firstName}" />
<h:outputLabel value="#{msgs.UserDetailJobTitle}" for="jtitle" />
<h:outputText id="jtitle" value="#{userGridBean.selectedUser.jobTitle}" />
<h:outputLabel value="#{msgs.UserDetailLastName}" for="lname" />
<h:outputText id="lname" value="#{userGridBean.selectedUser.lastName}" />
<h:outputLabel value="#{msgs.UserDetailEmployeeId}" for="empid" />
<h:outputText id="empid" value="#{userGridBean.selectedUser.id}" />
<h:outputLabel value="#{msgs.UserDetailDateOfHire}" for="doh" />
<h:outputText id="doh" value="#{userGridBean.selectedUser.DOH}" />
<h:outputLabel value="#{msgs.UserDetailLocation}" for="location" />
<h:outputText id="location" value="#{userGridBean.selectedUser.location}" />
<h:outputLabel value="#{msgs.UserDetailStatus}" for="status" />
<h:outputText id="status" value="#{userGridBean.selectedUser.status}" />
<h:inputHidden /> <h:inputHidden /> <h:inputHidden /> <h:inputHidden /> <h:inputHidden />
<h:outputLabel value="#{msgs.UserDetailComments}" for="comments" />
<h:outputText id="comments" value="#{userGridBean.selectedUser.comments}" />
<h:inputHidden /> <h:inputHidden /> <h:inputHidden />
<p:commandButton onclick="submit()" ajax="false" action="#{userDetailBean.navigation()}" value="Retur to User Grid" />
</h:panelGrid>
</p:tab>
</p:tabView>
</td>
</tr>
</table>
</h:form>
</c:if>
</ui:define>
</ui:composition>
</body>
I've tried everything I can think of for the second button: ajax="false"; onclick="submit()"; ajax="false" onclick="submit"; I've tried implicit navigation with a redirect as well as a navigation rule with a redirect. The action methods userDetailBean.submitChanges() and userDetailBean.navigate() both return the same string, which corresponds to a navigation rule in my faces-config file. The submitChanges method gets called, but my navigate method does not. I'm not filling the fields with any data at this point, I'm just trying to get the basic navigation to work. Why isn't my commandButton on the second tabView working?
Another reason that a commandbutton isn't been invoked is that the rendered attribute of the button or one of its parents evaluated false during apply request values phase of the form submit.
You have actually none, but those <c:if> tags does similar thing, only during view build time instead of view render time. The view params are not applied during building the view, but only thereafter. That's exactly why #{userDetailBean.view} is always empty.
I have never used such a construct with <c:if>, but I've had similar views like this where this all just works with a #ViewScoped bean where the rendering property is been applied on a fullworthy JSF component instead of <c:if>.
As first step, get rid of <c:if>s and move their tests into rendered attribute of the <h:form>s they are wrapping:
<h:form rendered="#{empty userDetailBean.view}">
...
</h:form>
<h:form rendered="#{not empty userDetailBean.view}">
...
</h:form>
If in vain (I guess that this will fail because you aren't using ajax and the viewparams are not preserved) and the bean is indeed #RequestScoped, then you need to mark it #ViewScoped to preserve the rendering conditions.
Related questions:
JSF h:commandLink is not being invoked
Unrelated to the problem, I'd rather use <h:panelGroup /> instead of <h:inputHidden /> to "fill" the empty cells of the table. They are cheaper to encode and decode and also ends in better HTML.

Resources