JSF 1.2/Seam 2.2 - validator is skipped when input it empty - jsf

I am trying to call validateLength in JSF (xhtml file of seam)
<f:validateLength minimum="2" maximum="512"/>
It works for values such as text length 513 and 1 (i.e. it shows a warning, but not for 0)
The input text filed for which it is being used is set to required=false (so that it can use a4j support for empty fields, I have to show a preview based on the input)
The problem that I see is that there a validator method in a helper class but it gets ignored when the length of input is 0 (ie I put nothing , it works for non-empty values).
I also have a NullableStringConverter here but what I have noticed that as soon as that converter sets the value of null of empty string, the validator gets skipped. Here is the complete snippet of in the inputText
<h:inputText id="linkNameInput"
value="#{someHelper.name}"
validator="#{someHelper.validateMethod}"
required="false">
<f:validateLength minimum="2" maximum="512"/>
<f:converter converterId="NullableStringConverter" />
</h:inputText>
I would just like the ability to validate an empty string in a validator.

I would just like the ability to validate an empty string in a validator.
That's not possible in JSF 1.x. That's only possible since JSF 2.0 (in favour of JSR303 Bean Validation support).
I'm not sure why you'd like to validate the empty string in the custom validator. There you normally use the required="true" attribute for this. If the sole goal is to change the required message, then just use requiredMessage attribute.
<h:inputText ... required="true" requiredMessage="Please enter name" />

As mentioned already, validating an empty input String in a JSF 1.2 component is not supported. However, you can check for this null/empty model value in your backing bean on form submit and add a FacesMessage that is mapped to that specific input field. This would allow integration with server-side component-specific error message display (<h:message for="componentId" />).
FacesContext.getCurrentInstance().addMessage("componentId",
facesMessageForComponent);

Related

Select input text on validation error in JSF

i have an input text and i want to select the value inside the text area upon validation error. it is an inputtext. I am using focus to set the focues on the field. Code does throw an error but i want the input values to be selected too
<p:focus for="inputText" />
<p:inputText id="inputText" value="#{bean.value}" required="true" rendered="#{bean.method}" styleClass="xyz"/>
The PrimeFaces p:focus automagically focusses the first invalid input. So effectively, there is nothing PrimeFaces related the rest of the solution. Client-side it is all html
For selecting text when the input focussed, use something like
<p:inputText onfocus="this.setSelectionRange(0, this.value.length)" .../>
You can extend it to first check if the input is invalid by checking for the presence of an error class and not select anything if it is not invalid (not tested):
<p:inputText onfocus="$(this).hasClass('ui-state-error' ? this.setSelectionRange(0, this.value.length) : return" .../>
if you want this for all inputs or don't want any inline javascript, create a jquery eventhandler

Omnifaces validateMultiple component only takes UIInput values, any workaround for considering UIOutput too?

So, I have an Address to validate and it has 4 input fields and 4 output fields, basically the 4 output fields are city,state,county and municipality. There are not editable, so they will be populated by zipCode lookup only. But when I validate , I need to pass in all the values, the lookup values too.
<o:validateMultiple> only takes in Input Component values, so I tried to make them h:inputText too and then disabled=true since they aren't editable, but looks like <o:validateMultiple> ignores values of disabled input components as well. So, any alternatives?
Initially I did it bu embedding all the ids with respective bindings using f:attributes on the first inputText component and used JSF validator to grab getAttributes and validated that way, which worked OK, but since validateMultiple reduces lot of that, I wanted to use this , but looks like it is not straight forward.
Something like this could have helped :
<o:validateMultiple id="myId" components="foo bar baz" validator="#{bean.validateValues}" />
<h:message for="myId" />
<h:inputText id="foo" />
<h:inputText id="bar" />
<h:inputText id="baz" />
public boolean validateValues(FacesContext context, List<UIComponent> components, List<Object> values) {
// ...
}
Any help is appreciated!
Thanks!
Use <h:inputHidden> if you need hidden inputs.

<h:message> unable to find component in <ui:repeat>

I am building a table using a <ui:repeat> tag, and its length is dynamic. Each row has a <h:inputText> field. When the form is submitted, it sets the values from the form into a hashmap. That all works great, except for the validation. I need to tell the <h:message> which input it belongs to using the "for" attribute. I've tried to create a unique ID per row, based on the name of the item being used to create the row. But the <h:message> tag remains empty when I submit an invalid input, and I get the following output on the servers log (JBoss 7.1):
[javax.enterprise.resource.webcontainer.jsf.renderkit]
Unable to find component with ID nTAS in view.
Here is the XHTML:
<ui:repeat var="item" ...>
...
<h:inputText value="#{bean.chosenItems[item.name]}" id="n#{item.name}" >
<f:validateLongRange minimum="0" maximum="10" />
</h:inputText>
<h:message for="n#{item.name}" />
...
</ui:repeat>
In order to at least get some kind of error message in the browser, I also added this near the top of my page, and it works:
<h:messages styleClass="error" />
It displays this message:
j_idt13:j_idt17:1:n: Validation Error: Value is not of the correct type.
And that kind of shows part of the problem, since the ID is that strange code at the start of the message, and it starts with "n", but doesn't contain the item's name. If I look at the source in the browser, the ID is actually: id="j_idt13:j_idt17:1:nTAS"
If I look at other components, outside of the table, they also have cryptic IDs, apparently generated by JSF.
And what is really weird is that when I input "asdf" a second time, and re-submit the form, it then calls the action method on the bean, instead of again failing during validation phase!! How can that be?!
Thanks for any hints,
John
You cannot create IDs dynamically with el expressions. And the "cryptic" IDs are indeed generated by jsf if you don't assign an ID to a component.
But you don't need to care for the uniqueness of your ids in ui:repeat. JSF does it for you (the "1" in the generated id string is the counter for your repeated component). Just give your input field a "fixed" id and reference it in your h:message:
<h:inputText value="#{bean.chosenItems[item.name]}" id="myID" >
<f:validateLongRange minimum="0" maximum="10" />
</h:inputText>
<h:message for="myID" />

h:selectOneMenu required="true" reverts to bean value on validation failure

I have something like this on a create/edit form:
<h:selectOneMenu value="#{bean.value}" required="true" ... >
<f:selectItem itemLabel="-- Select --" itemValue=""/>
<f:selectItems .../>
</h:selectOneMenu>
In the create new object case, the required validation works as expected.
In the edit object case, if I change a valid value to the placeholder "-- Select --", I get the validation failure w/expected requiredMessage because itemValue is blank (""); however, the HTML <select> reverts to whatever option was already selected from the bean, rather than retaining the invalid user input from form submission.
To reiterate, the required=true on the h:selectOneMenu itself works fine, generating the expected message - the only thing that's wrong is the value reverting to the bean value, instead of retaining the blank submitted value. (I confirmed with Chrome developer toolbar that an empty string is indeed being POSTed for the <select>.)
Why is this happening? More precisely, why is h:selectOneMenu not behaving like h:inputText, where the UIInput displays the invalid user input from the form, and does not refresh its value from the bean? Both of these controls extend the same UIInput base class and implement EditableValueHolder, so I expect their lifecycle would behave the same.
Also, to clarify, I do not have the INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL context param anywhere in web.xml.
This is a JSF application on Mojarra 2.1.3 / Glassfish 3.1.1.

What is the JSF behaviour, if you bind the same backing bean property to two input fields in the same form?

Is there a defined behaviour in JSF, if two input fields are bound to the same session scoped Backing Bean property.
Here is my code snippet
<h:form id="myForm">
<h:inputText id="field1" value="#{TheBackingBean.theProperty}" />
<h:inputText id="field2" value="#{TheBackingBean.theProperty}" />
<h:commandButton id="continueButton" action="#{TheBackingBean.doSomething}" />
</h:form>
My question: If field1 and field2 receive different values, what will be bound to the backing bean property? Is this even allowed?
I know this is a crude scenario. My motivation is, that we have htmlunit tests running for our application. In our JSF application we want to use a cool ajaxified custom component. This doesnt work together very well with htmlunit. So my idea was, I just put in a hidden field that binds to the same property. The unit test then fills the hidden field instead of the "real" thing.
Regards
I think this kind of code is allowed, but I am not sure of the value of theProperty after the submission. What I think is that JSF will do the following:
TheBackingBean.setTheProperty(field1.value);
TheBackingBean.setTheProperty(field2.value);
However, nothing - as far as I know - specifies the order of the setter calls. Thus, after the update values JSF phase, you will not be sure if theProperty will be equal to field1.value or field2.value.
Concerning your scenario, you say that you want to bind the same property to an inputText and an hiddenText. As the hiddenText will not submit its value, unlike the inputText, this problem will not occur. Indeed, if you have this kind of JSF code:
<h:inputText id="field1" value="#{TheBackingBean.theProperty}"/>
<h:inputHidden id="field2" value="#{TheBackingBean.theProperty}"/>
then JSF will only do:
TheBackingBean.setTheProperty(field1.value);
during the submission phase.

Resources