Search code examples
jsfnumber-formatting

f:convertNumber failing when currencySymbol is obtained from bean via EL


Hi in my project I need to visualize currency value, as far in my f:convertNumber

I use a fixed currencySymbol; everything is ok, but when I try to get the symbol with an expression language like this:

<h:outputText value="#{rowItem.value}">
    <f:convertNumber currencySymbol="#{rowItem.getCurrencySymbol()}" groupingUsed="true" maxFractionDigits="2" type="currency" />
</h:outputText>

it is like the method getCurrencySymbol is not called, I am sure there is something I am missing.


Solution

  • That will happen if #{rowItem} is only available during view render time, such as when it's specified by <h:dataTable var="rowItem">, as the variable name itself already suggests. It can also happen if #{rowItem} gets changed between building the view and rendering the view, such as when it's coming from a dropdown component in the same form. The <f:convertNumber> is namely a taghandler, not an UI component. It gets executed during view build time, not during view render time. The desired #{rowItem} value is not per definition available during view build time.

    This all is explained in JSTL in JSF2 Facelets... makes sense? In that answer, you can substitute "JSTL" with <f:convertNumber> as they both are taghandlers and thus have exactly the same lifecycle.

    There's no solution in standard JSF API without creating a custom converter and changing the view or model. You can find possible solutions in this answer: How to set converter properties for each row/item of h:dataTable/ui:repeat?

    The JSF utility library OmniFaces offers <o:converter> out the box for exactly this problem. Use it as follows:

    <h:outputText value="#{rowItem.value}">
        <o:converter converterId="javax.faces.Number" currencySymbol="#{rowItem.getCurrencySymbol()}" type="currency" />
    </h:outputText>
    

    (note that I omitted the other two properties as those are the default already when type="currency" is used)