passing validator to a custom component, fails - validation

I have a simple inputText with a validator:
<ice:inputText
id="test"
value="#{applicationBean.selectedApplication['name']}"
validator="defaultFieldValidator"
required="true"></ice:inputText>
<ice:message
styleClass="graValidationMessage graNotRequired"
for="test" />
You may have noticed that I specified a validator: defaultFieldValidator and all works fine.
I now make a component to act like a wrapper for the inputText named: inputTextValidated:
<ice:inputText
id="#{id}#{required}"
value="#{bean[field]}"
rendered="#{rendered}"
styleClass="#{styleClass} #{not required ? 'graNotRequired':''}"
style="width: #{width};"
partialSubmit="#{partialSubmit}"
disabled="#{disabled}"
required="#{required}"
validator="#{validatorClass}">
</ice:inputText>
If I try now to call this component (with the same validator for beginning passed now through a parameter):
<gra:inputTextValidated
id="inputText"
bean="#{applicationBean.selectedApplication}"
field="#{fieldValue}"
validatorClass="defaultFieldValidator"
renderLabel="false"
required="true"
disabled="false"
width="90%"
height="#{secondTabComponentsHeight}">
</gra:inputTextValidated>
if fails with the following error:
Identity 'validatorClass' does not reference a MethodExpression instance, returned type: java.lang.String
So the problem is when sending the validator name to my custom component.
Do you see a work-around?
Thanks.

I've ended up using
<f:validatorId validatorId="#{validatorClass}"/>
inside my inputText component

Related

Jsf action for an ajax request is not called when field is required

Hi I have the following jsf component
<h:inputTextarea id="in"
value="#{mycontroller.myvalue}"
title="sometitle"
readonly="false"
required="true"
rows="10"
styleClass="myclass"
immediate="false"
label="somelabel"
rendered="true" >
<f:ajax event="inputChange" />
</h:inputTextarea>
Whenever a change occurs in inputTextarea the function mycontroller.setMyValue is called that sets the attribute "myvalue" to the corresponding value. However, the setMyValue is not called whenever myvalue="" (empty String), i.e. the content of the text area is deleted. This has as a result the myValue to have an older value whenever mycontroller calls the getMyValue.
However if required="false" then even if myvalue is an empty string the setMyValue is called.
I've tried to change the event in the ajax from inputChange to blur...but nothing happened. I have the same behaviour.
Any ideas how to fix this?
Thanks

Interdependent components validation [duplicate]

In a basic registration screen (with button register records the screen) there are two panels:
Data panel:
Address panel:
I can register by completing only the Data panel. It is not necessary to fill the Address panel. However, if at least one field of the Address panel is filled, then all other fields in the same panel should be required.
How can I achieve this?
You need to check in the required attribute if the other inputs have submitted a non-empty value. Since this can result in quite some boilerplate, here's a kickoff example with only 3 input components.
<h:form id="form">
<h:inputText id="input1" value="#{bean.input1}" required="#{empty param['form:input2'] and empty param['form:input3']}" />
<h:inputText id="input2" value="#{bean.input2}" required="#{empty param['form:input1'] and empty param['form:input3']}" />
<h:inputText id="input3" value="#{bean.input3}" required="#{empty param['form:input1'] and empty param['form:input2']}" />
</h:form>
An alternative is to bind the components to the view and use UIInput#getValue() to check the value of the previous components and UIInput#getSubmittedValue() to check them for next components (components are namely processed in the order as they appear in the component tree). This way you don't need to hardcode client ID's. You only need to ensure that binding names doesn't conflict with existing managed bean names.
<h:inputText binding="#{input1}" value="#{bean.input1}" required="#{empty input2.submittedValue and empty input3.submittedValue}" />
<h:inputText binding="#{input2}" value="#{bean.input2}" required="#{empty input1.value and empty input3.submittedValue}" />
<h:inputText binding="#{input3}" value="#{bean.input3}" required="#{empty input1.value and empty input2.value}" />
You'll understand that this produces ugly boilerplate when you have more and more components. The JSF utility library OmniFaces has a <o:validateAllOrNone> validator for the exact purpose. See also the live demo. Based on your quesiton tags, you're using OmniFaces, so you should already be set with just this:
<o:validateAllOrNone components="input1 input2 input3" />
<h:inputText id="input1" value="#{bean.input1}" />
<h:inputText id="input2" value="#{bean.input2}" />
<h:inputText id="input3" value="#{bean.input3}" />
First you should add a method to backing bean something like this:
public boolean isAddressPanelRequired() {
// Check if at least one field is entered
// and return true if it is and false othervise
}
Each input element on address panel should have required="#{backingBean.addressPanelRequired}"
Then add onblur ajax listener on each input component on address panel which process that component, and updates address panel.

Submit empty value to bean anyway on input with required="true"

I've the below input with required="true":
<p:inputText value="#{bean.value}" required="true">
<p:ajax event="change" listener="#{bean.change()}" />
</p:inputText>
When user changes the value, the listener is fired and I can access the changed value. When user empties the field, the listener is not fired and the empty value is not updating in my bean. I gather that this is caused by requried="true". I would like to update my bean with empty value and fire the listener anyway when the user empties the field. How can I achieve this?
You can just use expression language (EL) in the required attribute too. You can then just check if the main submit button of the form has been pressed. Imagine that your form has a "Save" button like below,
<p:inputText ... required="true">
<p:ajax ... />
</p:inputText>
...
<p:commandButton ... action="#{bean.save}" />
Then you can let the required attribute evaluate true only if the button is invoked. You can achieve that by referencing the component via binding and checking if its client ID is present in the HTTP request parameter map:
<p:inputText ... required="#{not empty param[save.clientId]}">
<p:ajax ... />
</p:inputText>
...
<p:commandButton binding="#{save}" ... action="#{bean.save}" />
Note that #{save} is as-is and may absolutely not be bound to a backing bean, and that the variable name must be unique in the current view and EL scope.
See also:
How to let validation depend on the pressed button?
The issue is that if the user clears the required input field then 'required' validator throws an exception and bean setter will not be called. When the form is reloaded then cleared value will show up again from the bean. Here is my workaround:
public String getSomething() {
return isFormValueEmpty("form:something") ? null : this.something;
}
private Boolean isFormValueEmpty(String formFieldName) {
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
String formValue = ec.getRequestParameterMap().get(formFieldName);
logger.debug("Check if form value is empty: [{}] [{}]", formFieldName, formValue);
return StringUtils.isEmpty(formValue);
}

Is there a way to prevent JSF from displaying previous/outdated content in h:selectManyMenu after validation error?

I have a form with, say a text field and a multi-select field.
<h:form id="form2">
<h:messages for="text3" />
<h:inputText id="text3" value="#{danielBean.text3}" required="true"/>
<br/>
<h:messages for="select1" />
<h:selectManyMenu id="select1" value="#{danielBean.selStrings}"
style="height:8em;" required="true"/>
<f:selectItems value="#{danielBean.allStrings}" var="_item" itemLabel="#{_item} (length #{_item.length()})" />
<br/>
<p:commandButton
value="Submit"
action="#{danielBean.save()}"
update=":form2"
>
</h:form>
On submit, both get validated, and if validation is successful, the relevant variables in the backing bean are updated. Fair enough.
The problem happens when the validation (of the multi-select) is NOT successful. In my Bean, I have (particularly for the List<String>s allStrings and selStrings)...
#PostConstruct
public void init() {
text3 = "";
allStrings.clear();
allStrings.add("This");
allStrings.add("is");
allStrings.add("a");
allStrings.add("test");
selStrings.clear();
selStrings.add("a");
}
...so that the multi-select has one pre-selected option. If the user unselects that option (i.e. no options chosen), the validation will -of course- fail, an error message will be displayed...
...but the multiselect will not be empty. It will show the content from the bean, i.e. "a" selected. This is confusing to the user - getting an error message "input required", and being shown a filled-out field.
This appears to be a feature of JSF's lifecycle, see this article by BalusC:
"When JSF renders input components, then it will first test if the submitted value is not null and then display it, else if the local value is not null and then display it, else it will display the model value."
This works fine for the text field text3, because it submits as an empty string, not null.
The problem is that zero selected options from a multi-select means that the submitted value is null, that the local copy (I guess, since it's the first submit) is null, so that the model value ("a" selected) is displayed.
I do not want that.
How can I force JSF to use the null value it got submitted when rendering the validation response?
Thanks in advance
Antares42
There is no solution for this (other than reporting an issue to JSF guys and/or hacking in JSF source code). There's however a workaround: update only the components which really need to be updated on submit. Currently, you've set ajax to update the entire form. How about updating just the messages?
<h:messages id="text3_m" for="text3" />
...
<h:messages id="select1_m" for="select1" />
...
<p:commandButton ... update="text3_m select1_m" />
You can if necessary make use of PrimeFaces Selectors to minimize the boilerplate if you have rather a lot of fields:
<h:messages for="text3" styleClass="messages" />
...
<h:messages for="select1" styleClass="messages" />
...
<p:commandButton ... update="#(.messages)" />

Adding custom validators dynamically

Here is the pseudo code of what I'd like to achive:
<h:inputText id="inputId">
for -> validatorId : validatorIdArray
{
<f:validator for="inputId" validatorId="#{validatorId}"/>
}
</h:inputText>
I'd like to add custom validators to my input component dynamically. I have the validator names stored in an array or List, but so far I haven't managed to figure it out how to generate the validator tags.
Preferrably I'd like to have a full Facelets solution.
I tried to use <c:foreach> first but with the wrong namespace.
Now that I corrected it, it works as expected:
<h:inputText id="inputId">
<c:forEach items="#{validatorIdArray}" var="validatorId">
<f:validator for="inputId" validatorId="#{validatorId}"/>
</c:forEach>
</h:inputText>
try f:validateBean if you are using JSF2

Resources