Search code examples
validationcomboboxxpagesnumeric

How to display selected numeric values in a comboBox


I have a numeric field in a Notes form connected to a combobox in the xpage. the values from the combobox is a list of decimal values, 1,02, 1,03 etc but they are stored as text in the keyword documents

The combobox is of type "string" (no converters) but it doesn't seem to matter if I change it to a "decimal" using converters.

comma is a decimal separator in Sweden

I fetch the keyword values using a @dbLookup

something like this. @DbLookup(db,"vwLookupCat","BONUS","KeyWord")

When I save the document the values from the keyword document is saved as a numric value as it should. but the combobox is no longer showing the correct selected value (in edit mode) and displayes a validation error when I change it because the value is now numeric and not text as in the combobox keyword values. or because the field was initially a text field, but when saved it is a numeric field.

enter image description here

enter image description here

enter image description here

<xp:comboBox id="comboBox7" value="#{doc.bonus}">
                    <xp:this.converter>
                        <xp:convertNumber type="number"></xp:convertNumber>
                    </xp:this.converter>
                    <xp:eventHandler event="onchange" submit="true" refreshMode="partial" refreshId="tbl"></xp:eventHandler>
                    <xp:selectItem itemLabel="Välj Bonus" itemValue="0"></xp:selectItem>
                    <xp:selectItems>
                        <xp:this.value><![CDATA[#{javascript:@DbLookup(db,"vwLookupCat","BONUS","KeyWord")}]]></xp:this.value>
                    </xp:selectItems>
                </xp:comboBox>
  • Note that I am not using any validators on the combobox
  • I can't change the keyword field type to numeric as this is used on many other places
  • if doesn't help to use @Text (@Text(@DbLookup(db,"vwLookupCat","BONUS","KeyWord")))

How should I tackle this problem?

thanks in advance

Thomas

Seem to be a similar question here without solution


Solution

  • I can think of 2 ways you can go about it, both of which require you to make use of beans, hopefully you should already be familiar with the concept.

    The conceptually righteous

    The converter stays where it is. After all you want to deal with a number, you are saving a number. The converter instructs the framework to convert the returning string value from the POST into a number, and that is what you want, since also the destination field bound with the component is saved as a number.

    The problem is matching such value with the list of values used to populated the options. Why? Those values are not numbers.

    The solution is custom building the options rather than letting the framework doing the autoboxing from the array of string values returned from dblookup.

    It pains me to write ssjs+formula but the call should be something like this:

    <xp:selectItems
        value="${javascript:myBeanName.getSelectItems(@DbLookup(db,"vwLookupCat","BONUS","KeyWord"))}">
    </xp:selectItems>
    

    The bean method:

    public List<SelectItem> getSelectItems(String[] values) {
        List<SelectItem> options = new ArrayList<SelectItem>();
    
        for (String value : values) {
            options.add(new SelectItem(Double.valueOf(value), value));
        }
    
        return options;
    }
    

    By doing this you are creating options with comparable values.

    The only problem remaining is the utterly counterintuitive converter provided by IBM. Because you don't know what choosing 'number' does internally, whether it will be a Integer, a Double, a BigDecimal etc... you're stuck with more uncertainties than certainties. I have my own number converter but since I know how the IBM one works I think you can get away with the problem by specifying an additional param to the converter.

        <xp:this.converter>
            <xp:convertNumber type="number" integerOnly="true" />
        </xp:this.converter>
    

    I know, I know, integerOnly makes you think it will convert the value to Integer. It doesn't, it converts to Double. Lucky you! Imagine you needed an Integer!

    The conceptually crappy

    The other approach is to bind the combobox to a view scoped variable. You would initialize the variable with the string converted doc value at page load and then work with that. At save time you would read the view scoped variable, convert it back to number and push the number to the doc field before saving it.