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

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.

Related

Type-appropriate searching in dropdowns and search boxes in frontend

I have used custom converter classes with annotations like #FacesConverter(forClass = Date.class) to override the JSF default string representation of Date and Boolean objects in the frontend. I have two problems with this:
Date works as expected – all Date objects have a consistent representation in the frontend. However, Boolean works only if I change the annotation to #FacesConverter("mypackage.presentation.BooleanFormatConverter") and then explicitly invoke it in my xhtml, each time I want to use it, as <f:converter converterId="mypackage.presentation.BooleanFormatConverter" />.
I am changing the string representation of booleans to Yes/No, and I have filter boxes on boolean columns on my datatable with those string values. However, it does not seem to recognise that the string values correspond to the boolean true/false. I don't know how to fix this without explicitly changing the type of the booleans to string in the backend, then treating those as string columns in my datatable (and for other reasons, I'd rather keep types distinct and avoid explicitly converting everything to a string in the backend).
Quite simple in the end, following Kukeltje's suggestion: a boolean in the backing bean (which does not need to be done per-column) and changing the xhtml:
<p:selectCheckboxMenu value="#{myView.yesNoCheckbox}" label="Select" onchange="PF('tableE').filter()" scrollHeight="150" filter="true" filterMatchMode="contains">
<f:selectItem itemValue="#{true}" itemLabel="Yes"/>
<f:selectItem itemValue="#{false}" itemLabel="No" />
</p:selectCheckboxMenu>
the only disadvantage is that this part must be done manually per column (my datatable has an obscene number of columns, which is why I wanted a simple global way of doing this, such as a converter).

input component inside ui:repeat, how to save submitted values

I'm displaying a list of questions from database and for each question I have to display a list of options, in this case radio buttons.
<ui:repeat value="#{formData.questions}" var="question">
<div>
<p:outputLabel value="#{question.name}" />
<p:selectOneRadio value="#{formData.selectedOption}">
<f:selectItems value="#{formData.options}" />
</p:selectOneRadio>
</div>
</ui:repeat>
I need to save the checked option for each question.
How can I do this?
You need to associate the input value with the repeated variable var in some way. Right now you're not doing that anywhere and basically binding all input values to one and same bean property. So, when the form gets submitted, every iteration will override the bean property everytime with the value of the current iteration round until you end up getting the value of the last iteration round. This is definitely not right.
The simplest way would be to directly associate it with the object represented by var:
<p:selectOneRadio value="#{question.selectedOption}">
In your specific case, this only tight-couples the "question" model with the "answer" model. It's reasonable to keep them separated. A more proper solution in your specific case is to map it with currently iterated #{question} as key (provided that it has a proper equals() and hashCode() implementation, obviously):
<p:selectOneRadio value="#{formData.selectedOptions[question]}">
With:
private Map<Question, String> selectedOptions = new HashMap<>();
Regardless of the approach, in the action method, just iterate over it to collect them all.

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

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);

<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" />

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