0

I'm driven crazy by this bug :

I have the following field

<p:selectOneMenu id="selectOption"
        required="true"
        requiredMessage="#{bundle.mandatory_field_message}"
        rendered="#{myBean.previousOptionSelected eq 'Correct Option'}"
        value="#{myBean.selectedOption}">
    <c:if test="#{myBean.optionsList.size() ne 1}">
        <f:selectItem itemLabel="#{bundle.default_select}" itemValue="null" />
    </c:if>
    <f:selectItems value="#{myBean.optionsList}" var="opt"
            itemValue="#{opt}" itemLabel="#{opt.description}" />
    <f:ajax event="change" render="msgSelectOption" />
</p:selectOneMenu>
<p:messages id="msgSelectOption" for="selectOption" display="text" />

when I try to submit the form containing this field, the requiredMessage is displayed even if a value is selected and the value in the bean is actually correctly assigned

I currently am using primefaces 5.3 with jsf 2.0 (no : can't upgrade)

Sirmyself
  • 1,464
  • 1
  • 14
  • 29
  • You can't upgrade for production but you **can** just for the sake of this problem try a newer version and see if it is by accident something that was fixed. You are then a step closer to either finding a workaround or create a patch that solves it for the PF version you use... Cheers (and why do you use `f:ajax` inside a PF component instead of `p:ajax`? – Kukeltje Nov 29 '17 at 20:38
  • I did not work on this specific component before having this bug to correct. I usually do use `p:ajax` but I honestly don't see a difference except for the components attribute names – Sirmyself Nov 29 '17 at 20:45
  • What's bothering me is that it's the only component in the whole form that acts like so. And I got several fields pretty much build the same way that work just fine. – Sirmyself Nov 29 '17 at 20:47
  • I would have 2 suggestions for you to investigate: 1. Maybe Faces Converter is failing somehow (although I dont see it defined in code snippet). 2. Maybe getter for optionsList is not properly initialized in bean. – Dusan Kovacevic Nov 30 '17 at 06:36
  • I don't have a converter for this field. The objects created by the list are instances of the same class than the input's value. I already checked the getter with a debugger and the list is correctly initialized (another proof would be that I see the correct value(s) when I load the page) – Sirmyself Nov 30 '17 at 08:27

1 Answers1

0

I pretty much found an answer here, but I still will explain in this post because the reference answer does not address this particular issue directly :

The object that was used in the code example didn't seem to go through any kind of conversion. Although I could previously use objects without a converter, they were actually enum and this one is not. So it seems like anytime I need a custom object that is not an enum, I need to create a converter for it (either serialize the data manually into a string or simply use an id and recover the data from a list of the possible objects)

Here's what worked for me :

<p:selectOneMenu id="selectOption"
        converter="optionConverter"
        required="true"
        requiredMessage="#{bundle.mandatory_field_message}"
        rendered="#{myBean.previousOptionSelected eq 'Correct Option'}"
        value="#{myBean.selectedOption}">
    <c:if test="#{myBean.optionsList.size() ne 1}">
        <f:selectItem itemLabel="#{bundle.default_select}" itemValue="" />
    </c:if>
    <f:selectItems value="#{myBean.optionsList}" var="opt"
            itemValue="#{opt}" itemLabel="#{opt.description}" />
    <f:ajax event="change" render="msgSelectOption" />
</p:selectOneMenu>
<p:messages id="msgSelectOption" for="selectOption" display="text" />

with the following converter:

@FacesConverter(forClass = myPackage.OptionClass.class, value="optionconverter")
public class OptionConverter implements Converter{

    public Object getAsObject(FacesContext facesContext, UIComponent component, String submittedValue) {
        if (submittedValue != null && !submittedValue.trim().equals("")) {
            for (OptionClass opt : OptionListingService.getEntries()) {
                if (submittedValue.equalsIgnoreCase(opt.getUniqueID())) {
                    return opt;
                }
            }
        }
        return null;
    }

    public String getAsString(FacesContext facesContext, UIComponent component, Object value) {
        if (value == null || value.equals("")) {
            return "";
        } else {
            return ((OptionClass)value).getUniqueID();
        }
    }
}

Also note that I changed the value of itemValue="null" to itemValue="" in this item:

<f:selectItem itemLabel="#{bundle.default_select}" itemValue="" />

It was necessary because the converter would interpret the value as a String, thus would be trying to convert a string value with the id equal to "null". The code would still have worked, but I like (and it's also a better pratice) to manipulate data as clean as possible.

Thank you Dusan Kovacevic for pointing a possible Converter issue.

Sirmyself
  • 1,464
  • 1
  • 14
  • 29