How to block negative numbers on h:inputText with JSF - validation

I´m using jsf to build a form, and I have this kind of inputtext:
<div class="profile-info-row">
<div class="profile-info-name">Promoção:</div>
<div class="profile-info-value">
<span class="input-icon input-icon-right">
<h:inputText id="promocao" class="input-medium"
value="#{itemController.itemPreco.promocao}"
converterMessage="Valor inválido. (Ex.: 0.00)">
<f:convertNumber locale="pt"/>
<f:ajax event="change" render="promocaoMensagem"/>
</h:inputText>
</span>
<div class="help-inline mensagemErro">
<h:message for="promocao" id="promocaoMensagem"/>
</div>
</div>
</div>
and I have to block negative numbers and give a message to user inline that number is forbidden, how is working when the user types a invalid number on input..
Does someone know how I can do that?

Use <f:validateLongRange> with a minimum of 0.
<h:inputText ...>
<f:validateLongRange minimum="0" />
</h:inputText>
The default validation message is:
Validation Error: Value is less than allowable minimum of '0'
Any custom validation message can be set via validatorMessage the same way as you did for converterMessage.

Related

Component doesn't show the validation/error message just an icon

I have an autocomplete with validator. If the validator fails, it doesn't show the error message. It is shown only in a tooltip.
<h:panelGroup styleClass="form-group">
<div class="col-md-3">
<p:outputLabel value="#{labels['product_console_ins_management_company']}"
for="managementCompany" />
<p:panel rendered="#{empty saveProduct.initShowId}" >
<div class="form-control">
<p:autoComplete id="managementCompany"
required="true"
requiredMessage="#{labels['product_console_ins_management_company_validation']}"
value="#{saveProduct.product.company}"
var="b" itemLabel="#{b.description}" itemValue="#{b}"
completeMethod="#{saveProductConsoleController.completeInstrumentFactory}"
process="#this" scrollHeight="300" forceSelection="true"
converter="components.SimpleTypeBeanCollectionArrayConverter">
<f:validator validatorId="managementCompanyValidator"/>
<f:attribute name="boundList"
value="#{domainData.instrumentFactoryList}" />
</p:autoComplete>
</div>
</p:panel>
<br />
<p:outputLabel
rendered="#{ not empty saveProduct.initShowId}"
value="#{saveProduct.product.company.description}" />
<p:message for="managementCompany" display="icon" />
</div>
</h:panelGroup>
Screenshot of the problem
This is exactly what you tell it to do and effectively your question is not related to the validator or the p:autocomplete.
From the PrimeFaces documentation (read it, use it, it IS usefull)
Display Mode
Message component has three different display modes;
text : Only message text is displayed.
icon : Only message severity is displayed and message text is visible as a tooltip.
both (default) : Both icon and text are displayed.
This can also be seen in the PrimeFaces showcase for the message(s) component
So if you want different behaviour, choose a different value ('text' or 'both')

primefaces p:fileUpload validation always shows default

I don't know how to custom validate primefaces p:fileUpload.
My code xhtml is:
<h:form id="agruparCVForm" styleClass="validacionform" enctype="multipart/form-data">
<p:messages id="messages" showDetail="false" autoUpdate="true" closable="true" escape="false"/>
<fieldset>
<div class="col">
<div class="dtPadding_bottom">
<p class="parrafoMargintop1em textSmall">
<h:outputText value="#{comunidadesBundle.textoAdjuntarDocumentoAsociar}" escape="false"/>
</p>
<p:fileUpload value="#{agruparComunidadController.comunidadAAgrupar.documentoAutorizacion}" mode="simple" skinSimple="true" required="true"/>
</div>
</div>
</fieldset>
<div class="float-cleaner marginTopBottom2em"></div>
<!-- Botones-->
<div class="ftr">
<h:commandButton value="#{comunidadesBundle.guardarCambiosBtn}" title="#{comunidadesBundle.guardarCambiosBtn}" action="#{agruparComunidadController.agrupar}" styleClass="buttonContrast azul textSmaller MarginBottom2em floatRMobile"/>
</div>
</h:form>
The action="#{agruparComunidadController.agrupar}" never gets called as the jsf validation is performed before getting the standard message from the api.
The question is how can I put a customized error message?
I'm new to primefaces and I don't know how it gets valiated.
I need to validate this field when the form get's submitted. So it should check if the field is empty and display the custom message instead of the standard message choose:.....
Thank you in advance.

ajax validation error message [duplicate]

This question already has an answer here:
Custom JSF validator message for a single input field
(1 answer)
Closed 7 years ago.
how to add my own message for the client side validation in JSF.
<div class="ui-grid-row">
<div class="ui-grid-col-3" align="left">
<h:outputLabel for="cmpny" value="Company Name:" style="font-weight:bold" />
</div>
<div class="ui-grid-col-2">
<p:inputText id="cmpny" value="#{userData.cmpny}">
<f:validateLength minimum="10" />
<p:ajax execute="currentInput" update="company" event="blur" />
</p:inputText>
</div>
<div class="ui-grid-col-1" />
<div class="ui-grid-col-1">
<p:message for="cmpny" id="company" display="icon" />
</div>
<div class="ui-grid-col-5"></div>
</div>
</div>
<div class="ui-grid-col-3" align="left">
<h:outputLabel for="fnm" value="First Name:*" />
</div>
<div class="ui-grid-col-2">
<p:inputText id="fnm" value="#{userData.fnm}" validatorMessage="First Name cannot be left blank and must be greater than 3 characters" >
<f:validateLength minimum="4" />
<p:ajax execute="currentInput" update="firstname" event="blur" process="#this" />
</p:inputText>
</div>
<div class="ui-grid-col-7"><p:message for="fnm" id="firstname" display="icon,text"/></div>
With the help of "validatorMessage" attribute, I am able to show customized messages when ever the validation fails for the primeface elements like (inputText,calendar etc..,),.
You need to supply a message bundle via javascript. See PrimeFacesLocales for examples.
PrimeFaces User Guide, 7. Client Side Validation / 7.4 Messages.

How can I choose where the error message from the validator `required` appear?

How can I choose where the error message from the validator required appear?
The error message is now displayed at the bottom of my page but I want it next to my inputbox.
<p>Firstname: <h:inputText value="#{userBean.firstname}" required="true"/></p>
<p>Lastname: <h:inputText value="#{userBean.lastname}" required="true"/></p>
Those appearing at the bottom are actually unhandled messages which will only appear when the javax.faces.PROJECT_STAGE is been set to Development in web.xml.
You need a <h:message> to declare the location where the message should be shown. Further, you also need a <h:outputLabel> to represent the labels (which has semantic and usability advantages).
Here's the complete set:
<p>
<h:outputLabel for="firstname" value="Firstname:"/>
<h:inputText id="firstname" label="Firstname" value="#{userBean.firstname}" required="true"/>
<h:message for="firstname" />
</p>
<p>
<h:outputLabel for="lastname" value="Lastname:"/>
<h:inputText id="lastname" label="Lastname" value="#{userBean.lastname}" required="true"/>
<h:message for="lastname" />
</p>

AJAX within nested JSF Composite Component

I'm having a bit of trouble getting AJAX calls to fire properly in a nested composite component with Mojarra 2.0.3 and PrimeFaces.
The child composite component looks something like this:
<cc:interface componentType="therapy">
<cc:attribute name="therapyType" type="java.lang.String" required="true"/>
<cc:attribute name="patientId" type="java.lang.String" required="true"/>
<cc:attribute name="showHistory" type="java.lang.Boolean" required="false" default="true"/>
<cc:attribute name="width" type="java.lang.String" required="false" default="350px"/>
<cc:attribute name="maxHistory" type="java.lang.String" required="false" default="3"/>
<cc:attribute name="collectDoctor" type="java.lang.Boolean" required="false" default="false"/>
<cc:attribute name="collectCareDate" type="java.lang.Boolean" required="false" default="false"/>
<cc:attribute name="important" type="java.lang.Boolean" requred="false" default="false"/>
</cc:interface>
<cc:implementation>
<script>
function #{cc.clientId}Toggle(){
$("##{cc.clientId}_newbutton").toggle();
$("##{cc.clientId}_savebuttons").toggle();
if(#{cc.attrs.collectDoctor}){
$("##{cc.clientId}_doctor").toggle();
}
if(#{cc.attrs.collectCareDate}){
$("##{cc.clientId}_care").toggle();
}
$("##{cc.clientId}_newTherapy").toggle(50);
}
function #{cc.clientId}rowHighlight(event){
if(event.status == 'begin'){
$("##{cc.clientId}_loader").toggle();
}
if(event.status == 'success'){
$("##{cc.clientId}\\:histTable tr:eq(1)").effect("highlight", {color:"#FED17A", easing:"easeInCubic"}, 2000);
}
}
$(function(){
if(#{cc.attrs.important}){
$("div[class~='ui-panel-titlebar'][id^='#{cc.clientId}']").css("background", "#FED17A");
}
});
</script>
<h:form prependId="false">
<p:panel styleClass="mcoPanel" style="width:#{cc.attrs.width};">
<f:facet name="header">
<h:panelGroup>
<span id="#{cc.clientId}_title">#{cc.myType.word}</span>
<span id="#{cc.clientId}_newbutton" class="mcoPanel-controls">
<span onclick="#{cc.clientId}Toggle();">
<h:graphicImage name="page_new.gif" library="images"/>
</span>
</span>
<span id="#{cc.clientId}_savebuttons" class="mcoPanel-controls" style="display:none;">
<span id="#{cc.clientId}_loader" style="display:none;">
<h:graphicImage name="ajax-loader.gif" library="images" height="16" width="16"/>
</span>
<h:commandLink action="#{cc.saveNewTherapy}">
<f:ajax execute="newOnTherapy newExemption newDoctor newCareDate" render="#form" onevent="#{cc.clientId}rowHighlight"/>
<h:graphicImage name="action_save.gif" library="images"/>
</h:commandLink>
<span onclick="#{cc.clientId}Toggle();">
<h:graphicImage name="page_cross.gif" library="images"/>
</span>
</span>
</h:panelGroup>
</f:facet>
<div id="#{cc.clientId}_newTherapy" class="mcoPanel-new" style="display:none;">
<h:outputLabel for="newOnTherapy" value="Satisfied:" style="position:relative; top: -10px;"/>
<p:selectOneMenu id="newOnTherapy" label="Satisfied" value="#{cc.newOnTherapyValue}" style="width: 60px;">
<f:selectItem itemLabel=""/>
<f:selectItems value="#{cc.yesNoList}"/>
</p:selectOneMenu>
<br/>
<h:outputLabel for="newExemption" value="Exemption:" style="position:relative; top: -10px;"/>
<p:selectOneMenu id="newExemption" value="#{cc.newExemption}" style="width: 150px;">
<f:selectItems value="#{cc.exemptions}"/>
</p:selectOneMenu>
<span id="#{cc.clientId}_doctor" style="display:none">
<br/>
<h:outputLabel for="newDoctor" value="Doctor:"/>
<p:inputText id="newDoctor" value="#{cc.newDoctor}"/>
</span>
<span id="#{cc.clientId}_care" style="display:none">
<br/>
<h:outputLabel for="newCareDate" value="Care Date:"/>
<p:calendar id="newCareDate" label="Care Date" value="#{cc.newCareDate}" showButtonPanel="true">
<f:converter converterId="dateOfBirthConverter"/>
</p:calendar>
</span>
</div>
<h:messages id="#{cc.clientId}_messages" errorClass="errorMessage"/>
<p:dataTable id="histTable" value="#{cc.history}" var="item" rendered="#{cc.attrs.showHistory}">
<!-- Table Output -->
</p:dataTable>
</p:panel>
</h:form>
And the parent composite component looks something like this:
<cc:interface>
<cc:attribute name="title" type="java.lang.String" required="true"/>
</cc:interface>
<cc:implementation>
<h:outputScript name="containerpanel.js" library="js/components" target="head"/>
<p:panel toggleable="true" styleClass="contentPanel" toggleSpeed="500" style="width:1100px;">
<f:facet name="header">
#{cc.attrs.title}
<div class="ui-panel-titlebar-icon ui-corner-all ui-state-default contentSaveAll">
Save All
</div>
<div class="ui-panel-titlebar-icon ui-corner-all ui-state-default contentExpandAll">
++
</div>
<div class="ui-panel-titlebar-icon ui-corner-all ui-state-default contentCollapseAll">
- -
</div>
</f:facet>
<cc:insertChildren>
<!-- Child components go here -->
</cc:insertChildren>
</p:panel>
</cc:implementation>
The implementation is supposed to allow for any number of child components inside the container component.
The child components send ajax requests and update their internal components perfectly if they are placed on a page outside of the Container component. In addition, if I use the same structure of the container, but not an actual composite component, everything works just fine.
As soon as I place the child components as children of the Container component, that's where things go wonky. No ajax calls in the child components fire properly (i.e. the save commandLink) Using firebug to help debug this, I've been able to determine the following:
The ajax post request appears to be being sent. The "begin" onevent is firing, and looking at the console in firebug shows a post being made to the server, with the proper component ids and values being sent back.
The action in the backing bean is not being called. I have a print statement as the first line and it's not printing.
The ajax request appears to be completing properly, the "success" onevent is firing.
Nothing is being updated on the page. The form does not refresh, nor does the p:messages object at the top of the page.
Obviously I can do this without the Container component, but I would prefer to be able to of course take advantage of code reuse. Am I missing something obvious here that I need to do to get the ajax to work properly?
I am having the exact same problem with MyFaces 2.1.6.
I can't make AJAX calls from nested Composite Components using ClientBehavior in the interface of the CC.
Like moneyT wrote the server is being notified of the events specified in the ajax tag, but when the lifecycle went to phase 5 - Invoke Application, the event was null and no listener was called. More and more it looks like a bug in the implementation of MyFaces.
EDIT: I have found another solution which is much better than hardcoding ajax in the composite component. I have refactored the outer composite component to be facelet. It loses some of the quirks of the composites but it gets the job done. Also it is reusable.
The only solution (more of a workaraund than solution) I found is to hardcode ajax in the composite component rather than to use ClientBehavior, like this:
<composite:implementation>
<h:panelGroup layout="block" id="listBox" class="list-box-scroll-pane" style="height:#{cc.attrs.visibleLines*27 + 5}px; width:#{cc.attrs.width}px">
<h:inputText id="submit-value" style="visibility: hidden; width:0px; height: 0px;" value="#{cc.attrs.property}">
<f:ajax event="change"
render="carModel"
listener="#{carDetailsMediator.changeCarMake}"
onevent="initComboboxes"/>
</h:inputText>
<ui:repeat value="#{cc.attrs.items}" var="element" varStatus="loop">
<input id="input-#{cc.attrs.customId}-#{loop.index}" type="hidden"
value="#{element.value}" />
<div id="div-#{cc.attrs.customId}-#{loop.index}" class="list-box-row">#{element.label}</div>
</ui:repeat>
</h:panelGroup>
</composite:implementation>
However this workaround is not very good, because the idea behind composite components is that you can reuse them with many different options. Hardcoding ajax in it kind of limits the options.
I believe your problem is this:
<f:ajax execute="newOnTherapy newExemption newDoctor newCareDate" ...
The execute attribute can refer to the special keywords (Eg. #this, #form, etc...) or according to the documentation:
If a literal is specified, it must be a space-delimited String of component identifiers and/or one of the keywords.
When you are inserting this component as a child to the parent component then the component Ids are going to by dynamically determined and can't be referred to absolutely.

Resources