Highlight an inputText in JSF when a validation error occurs - jsf

I have a form with a lot of inputText, what I want is to highlight those who are not being filled with correct data.
I tried to use 'component.valid' but it always return that the field is invalid (i.e. fields are always red).
this is the code :
<h:inputText value="#{creerPersonne1.nom}" id="nom"
style="#{not nom.valid ? 'border-color:red;' : 'border-color:black;'}">
<f:validateRegex pattern="^[a-zA-Z]+$"></f:validateRegex>
</h:inputText>
this is the result :
note that the field is also highlighted when the page is loaded for the first time.

You should use component.valid instead of nom.valid.
component is an implicit EL object for the current input component. And component.valid calls the isValid() method of the server side component. The id argument cannot be used this way.
So you should change your code as follows:
style="#{ component.valid ? 'border-color:black;' : 'border-color:red;'}"
(Not related but you should better use style classes instead of hard coded styles. The valid check works for the styleClass attribute as well).

Related

Getting a null value passed to a Java function via BootsFaces datatable

I am trying to create a modal to send user-selected requests to an email address; however, I am having trouble getting the user-selected requests. I keep getting the null value passed through fooBean.setSelected(id).
Versions:
BootsFaces: 1.3.0
Java: 1.8.0
JSF: 2.0
Browser: Internet Explorer 11.2x
MCVE of thisThing.xhtml:
<b:dataTable value="#{fooBean.newRequests}"
var="foo"
onselect="ajax:fooBean.setSelected(id)"
ondeselect="ajax:fooBean.setSelected(id)"
selectedItems="row"
selection-mode="multiple"
selectedRows="#{foo.selected}"
saveState="false">
<b:dataTableColumn label="Select">
<b:selectBooleanCheckbox value="#{foo.selected}" />
</b:dataTableColumn>
<b:dataTableColumn label="Status" value="#{foo.status}" />
<b:dataTableColumn label="Request Number"
value="#{foo.requestNumber}"
data-type="string" />
<b:dataTableColumn label="ID" value="#{foo.id}" />
<b:dataTableColumn value="#{foo.storeName}"
label="Store Name" />
</b:dataTable>
MCVE of fooBean.java:
#ManagedBean(name="fooBean")
#ViewScoped
public class fooBean extends BeanBase implements Serializable {
private List<FooRecord> fooRecords = new ArrayList<FooRecord>();
private List<FooRecord> selectedFooRecords = new ArrayList<FooRecord>();
// ...
public void setSelected(String requestId) {
// This is not how I really do it, but it gives an idea
// with what I intend to do.
this.fooRecords.stream().filter(...).toggleSelection();
this.selectedFooRecords.stream().filter(...).toggleSelection();
}
}
Update:
I found out that I had the method called as getSelect instead of getSelected, so I fixed it and that part is done. I just remembered the real issue which is why a null parameter is being passed instead of the requestId. When I debug through the fooBean.getSelected(String requestId), it shows null being passed through as parameter. I have even tried:
<!-- Using varName.property -->
onselect="ajax:fooBean.setSelected(foo.id)"
<!-- Using just the property name -->
onselect="ajax:fooBean.setSelected(id)"
<!-- Using the loop variable -->
onselect="ajax:fooBean.setSelected(foo)"
Update 2:
How do I pass foo.id to the function?
There are only three parameters you can pass to the bean method:
The loop variable. In your example, that's foo. This parameter only works if the attribute selected-items is set to rows. Caveat: if you activate column or cell select mode, this parameter is still passed to the server, and it seems to be valid. Only that every attribute of this object is null.
typeOfSelection. This is either "row", "column" or "item". It determines what the user has selected. That, in turn, is determined by the attribute selected-items, so you hardly ever have to use this parameter. Just omit it from the parameter list.
indexes tells the JSF bean which rows, columns or cells have been selected. Note that in the first two cases this is either an individual number or - if multiple items have been selected - a comma separated list. If you've set selected-items="cell", indexes is a comma-separated list of objects containing the row and column index.
I suppose indexes or foo is the most useful parameter in your case.
Final remark: we'd like to add more flexibility, but this requires much more understanding of the internal API of JSF than even we have. Truth to tell, I'm not even sure we can pass arbitrary bean values without modifying the JSF engine itself. If anybody knows how to do that, please leave a message at our bug tracker.
Update:
Maybe the problem is caused by the modal. The modal is rendered at load time, but shown later, when the user has selected a row. Thing is, the modal isn't re-rendered automatically unless you add the content of the modal to the update attribute.

How to enable/disable SelectManyCheck based on method returned value?

Can anyone help in getting the returned value from a method in a bean to enable/disable components through ajax ex(SelectManyCheckbox, textbox ..etc) in a jsf page based on the selected radio button. First the SelectManyCheckbox component should disabled and based on the selection it should be enabled. The method is checking whether the value is "A" or "B" and it will return the value. Here is the method code:
private String firstToggle="True";
public String firstToggle(AjaxBehaviorEvent e){
firstToggle=requestType;
System.out.print("Value "+firstToggle);
return firstToggle;
}
Here it will return A or B.
However, When I am trying to disable/enable the SelectManyCheckbox component, the SelectManyCheckbox component won't pickup the value in the disabled attribute when the Value is B.
<p:selectManyCheckbox id="Cars" value="#{user.xyz}" layout="pageDirection" disabled="#{user.firstToggle}=='B')">
<f:selectItems value="#{user.xyz}" var="xyz" itemLabel="#{xyz}" itemValue="#{xyz}"/>
</p:selectManyCheckbox>
So please help
The reason why you don't want to use firstToggle as a Boolean/boolean as suggested per Tiny's comment is really not clear! However, if you have your reasons to do that or you are handling the firstToggle in another place and you want to use it's value 'A' or 'B' in two different p:selectManyCheckbox ("where one should be enabled and the other should be disabled" as you said), then you could implement the first one with disabled="#{user.firstToggle eq 'B'}" and the second one with disabled="#{user.firstToggle eq 'A'}" or disabled="#{user.firstToggle ne 'B'}".
In case, you want to work with Boolean/boolean following Tiny's suggestion, then just use the first one with disabled="#{user.firstToggle}" and the second one with disabled="#{not user.firstToggle}"
NB: Also private String firstToggle="True"; even if it's correct, it doesn't make any sense, either use Boolean/boolean and assigne true to it, or assign 'A' which seems to mean false regarding your context.

EL function not found in validator attribute

El function cannot be found using within validator attribute, which is dependent on dynamic or repeated values?
Function 'el:min' not found
#{el:min(a + b, c)}
<f:validateLongRange maximum="#{el:min(foo.bar, 10)}"/>
Just printing out the value is working where it is not working in the validator.
The error message Function 'el:min' not found was so misleading.
The problem was never the construct but it was an underlying NullPointerException on the nested property.
Since in one case the value was depending on a different component selection it was updated via ajax and the default value was null. Since the default value was null this misleading exception was thrown.
The value was a nested property, so it was not catched within the el function
Solution: disable the validator on default
<o:validator validatorId="javax.faces.LongRange" maximum="#{el:min(foo.bar, 10)}"
disabled="#{foo eq null}"/>
This construct should work just fine. The problem is most likely the scope of the variables which you've there and the timing (i.e. when do you need them? when are they "behind the scenes" changed?).
You need to understand that taghandlers like <f:xxx> run during view build time (like JSTL <c:xxx>). So their attribtues are resolved during view build time and would be filled with bean's default values. Perhaps you're performing some business logic on them while submitting the form and expecting that they would be reflected into the taghandler attribute. But this is not true. They were already evaluated during view build time and won't re-evaluate the values during processing the form submit.
If this is indeed the case, then you've basically the same problem which is already outlined and answered with various possible solutions in this answer: How to set converter properties for each row of a datatable? Apart form homegrowing a Validator for this, you could use OmniFaces <o:validator> for this:
<o:validator validatorId="javax.faces.LongRange" maximum="#{el:min(a + b, c)}" />

h:outputtext issue in passing attributes

I have a search screen where I search for a customer id and it consumes a webservice a returns list of objects. I display the results in a datatable.For a specific field , I have a method which provides the value based on a key value in each row of the list being iterated. The key value is productID. I set that in a bean named output. In the getCustomerValue method I call the method which provides the relevant value by passing the value of "productID". I use the below listed code to do the same.
<h:outputText id="customerID" binding="#{myBean.output}" value="#{customerBean.customervalue}">
<f:attribute name="myID" value="#{item2.customerService.productID}"/>
</h:outputText>
The value gets displayed properly when the page is loaded. I have hyperlink in the same page which basically calls the same webservice and renders the same page.But this time around all the values except the value listed above is being displayed. When I print the value of attribute "item2.customerService.productID" in the method "customervalue" , it is displayed as null.I am not sure why this value isn't being passed.
You're displaying this in a <h:dataTable>. The <f:attribute> is specific to the component itself, not to its generated HTML output. The <f:attribute> is evaluated during view build time, not during the view render time. At the moment JSF builds the view, the #{item2} is not present in the scope. It's only present in the scope when JSF renders the view.
You need to look for the solution by alternate means. It's unclear what JSF version you're using, but based on your question you're using JSF 1.2 (in the future questions, please explicitly mention the JSF impl/version you're using; in JSF 2.0 a lot of things can be done differently and much more elegantly).
My answer on your previous question of Passing parameters to a method in h:outputtext tag should be the best answer to your current problem. This is apparently not an option somehow. In that case, there are at least 3 alternative ways:
Move the property to the class behind #{item2}:
<h:outputText value="#{item2.customervalue}">
You've in there instant access to the customerservice property.
Get the current item inside the getter by evaluating EL programmatically:
public String getCustomervalue() {
FacesContext context = FacesContext.getCurrentInstance();
Long productID = context.getApplication().evaluateExpressionGet(context, "#{item2.customerService.productID}", Long.class);
// ...
}
(I assume that productID is a Long)
Bind the datatable's value to a DataModel:
private DataModel<Item2> items;
with
<h:dataTable value="#{customerBean.items}" var="item2">
and
public String getCustomervalue() {
Item2 item2 = items.getRowData();
// ...
}

Displaying custom error message for a blank field in a simple JSF application

I was trying out a simple JSF application, in which I need to check if the "name" field is blank, then display an error message.
The code which takes the field's value is:
<h:outputLabel value="Name"/>
<h:inputText value="#{greeting.name}" required="true">
<f:validator validatorId="NumValidator"/>
</h:inputText>
The control of the program does not go into the validator class, if the field is submitted without entering anything, and it displays the default error message:
j_id_jsp_869892673_1:j_id_jsp_869892673_4: Validation Error: Value is required.
How do i display a custom message for this ?
The Message.properties file stored the default validation messages. This file is contained in the JAR of the JSF implementation library.
If you look at the content of this file, regarding the required validation, you will see that:
javax.faces.component.UIInput.REQUIRED={0}: Validation Error: Value is required.
To define your own error messages, create a new properties file, add the adequate error message, for example:
javax.faces.component.UIInput.REQUIRED=Hey, you forgot to fill the input {0}!
(note that {0} will be replaced by the ID of the field)
then, in your faces-config.xml, define a new message-bundle:
<message-bundle>package.that.contains.the.properties.file</message-bundle>
So for example, if your my-messages.properties is stored in the foo/bar package, you will have to write:
<application>
...
<message-bundle>foo.bar.my-messages</message-bundle>
</application>
(note that you will not have to specify the .properties extension)
The way suggested by romaintaz is definitely way to go.
On the other hand if you are looking for more customization, you can use a phase listener that fires before render response phase as does some customizing.
For example first define the value for key as below:
javax.faces.component.UIInput.REQUIRED=INPUT_REQ_FAIL
then for input components that require validation have them pass a attribute using f:attribute .Then in phase listener iterate over the face messages and check for INPUT_REQ_FAIL and replace it with cutom message along with the attribute value for the component.
I think you should look at JSR 303! This is fully standard based user input, it works out of the box with JSF 2 (I use My Faces). And the nice thing is, no need for xml or properties files to specify custom messages.

Resources